简介:一份面向Linux初学者、进阶用户及服务器运维人员的系统命令速查手册,内容覆盖文件与目录管理、系统监控与用户权限、网络配置与远程访问、软件包管理等四大核心模块,并针对Debian/Ubuntu、CentOS/RHEL、Fedora、Arch等主流发行版的包管理差异做了对照说明。资源以单个docx文档交付,体积约15KB,轻量易携带,目前已积累129人学习。文档中每条命令均配有简明示例,如ls的-a/-l参数、tar的打包压缩用法、grep递归搜索、crontab定时任务、iptables规则查看等,方便对照练习与排错;同时补充了which、alias、history等高频辅助命令,可有效提升日常操作效率。无论是新手入门建立知识框架,还是运维人员作为快速查询手册,都具备实用价值。
1. Linux 系统常用命令:为什么同样是排查问题,有人三分钟有人三十分钟
Linux 系统常用命令这个标题,看着像一本命令字典,但真正拉开差距的从来不是背了多少条命令,而是知道哪些命令可以组合起来用。我帮同事排查一个服务启动失败问题时,他在目录里来回点了五分钟才找到日志,我用一条tail -f加上grep在十秒内定位到报错行——区别不在手速,而在理解命令的配合方式。这篇笔记不打算把命令手册抄一遍,而是把日常排查、运维、脚本编写里最高频的命令讲透:参数怎么设、什么时候用它、最常在哪里翻车。适合刚上手 Linux 的开发者、需要自己查日志和进程的运维新手,以及想把命令行真正变成生产力工具的从业者。
2. 文件与目录操作:路径规则、查看技巧与复制场景的参数差异
2.1 路径解析规则:为什么你 cd 不进去、cp 找不到文件
文件命令是 Linux 里使用频率最高的命令族,但很多人第一个坑就栽在路径上。常见做法是先pwd确认当前位置,再决定用绝对路径还是相对路径。绝对路径从/开始,在任何目录下都有效;相对路径依赖当前所在目录,脚本里最容易出问题——你在项目目录下写的cp config.ini ../backup/,换一个目录调用脚本,目标位置就完全变了。
# 打印当前工作目录 pwd # 回到上一个工作目录,适合在两个目录间反复切换 cd - # 回到当前用户的家目录 cd ~ # 用上一级目录和当前目录组合相对路径 cd ../ cp ./config.ini ../backup/cd -在日常排查时非常实用:你在/var/log看日志,切到/etc改配置,一条cd -就能回到刚才的目录,不需要重新敲路径。~代表当前用户的家目录,但要留意一个陷阱:脚本用sudo执行时,~解析成 root 的家目录而不是你当前用户的家目录,这会让很多写死的路径失效。我的习惯是脚本里不用~,改成显式的$HOME或绝对路径,避免 sudo 环境下行为不一致。
路径解析还有一个常被忽略的点:/开头的绝对路径不会被别名或当前目录影响,适合写进计划任务和执行脚本里。相对路径则要关注“当前目录是哪里”,这在后面的避坑章节还会提到。
2.2 ls 与 find:从“能看见”到“能找到”
ls是所有新人第一条接触的命令,但多数人只用默认输出,浪费了它定位文件的能力。排查文件时间、大小、权限时,组合参数比用鼠标点开图形界面快一个量级。下面是我常用的几个参数组合:
| 命令 | 作用 | 典型场景 |
|---|---|---|
ls -lh | 人类可读的文件大小 | 看大文件占用 |
ls -t | 按修改时间倒序 | 找最近改动的文件 |
ls -S | 按文件大小倒序 | 定位占用大的文件 |
ls -la | head | 含隐藏文件的头部列表 | 看目录里最近新增了什么 |
# 递归查找名字包含 error 的文件,忽略大小写 find /data/logs -iname "*error*" -type f # 找出 7 天内修改过的配置 find /etc -type f -mtime -7 # 找出超过 100M 的文件 find /data -type f -size +100M # 找出空目录,配合清理脚本很有用 find /data -type d -emptyfind和ls的分工不一样:ls适合在一个目录里快速浏览,find适合在整棵目录树里按条件定位。-mtime -7中的数字表示“多少天以内”,正数表示多少天以前,这个正负号经常让人搞反。-size +100M里的+表示大于,小于则直接用负数或没有符号,写脚本时先跑一遍find确认匹配结果,再进入删改步骤,能避免很多误操作。
2.3 cp、mv、rm 与 rsync:复制场景怎么选参数
复制和移动是所有运维操作的起点,参数选错轻则覆盖文件,重则丢失数据。先看几个高频用法:
# 保留权限和时间戳递归复制,备份目录时用 cp -rp /opt/app /data/backup/ # 目标已存在时不覆盖,批量合并时很安全 cp -n source.txt dest.txt # 仅在源文件更新时复制,适合增量同步小目录 cp -u source.txt dest.txt # 移动前逐个确认,防止误覆盖同名文件 mv -i old.conf new.conf-p保留的是权限、属主和时间戳,日志轮转和配置备份必须带上。-n在不希望覆盖任何已有文件时是安全网,但它和-u冲突,两个不能同时用。mv -i的交互确认看起来烦,但在批量移动时能避免同名覆盖——有一次我把一批配置移动到新目录,同名文件被静默覆盖,后面排查了很久才发现是这里的问题。
目录级别的同步使用rsync更可靠,它支持断点续传和只传输变更部分:
# -a 归档模式保留属性,-v 显示过程,--delete 删除目标端多余文件 rsync -av --delete /opt/app/ /data/backup/app/--delete是把双刃剑:它的本意是让目标目录和源目录完全一致,但如果你在源目录误删了一个文件,同步后目标目录里也没有了。我的习惯是第一次同步不加--delete,先跑-av看对比结果,确认无误后再决定要不要加。另外注意源路径末尾的/,rsync -av /dir /backup和rsync -av /dir/ /backup的结果不同——前者会创建一个dir子目录,后者把内容直接同步到目标目录。
3. 文本处理三件套:grep、sed、awk 让日志直接变成答案
3.1 grep:匹配、递归与上下文
日志文件是 Linux 排障的主要线索来源,而grep是打开线索的第一把钥匙。默认的简单匹配只能告诉你“有没有”,加上参数之后才能回答“在哪个文件、哪一行、旁边是什么”。这几个参数是我在生产环境中最常用的:
# 递归搜索指定文件类型,忽略大小写,显示行号 grep -rn --include="*.py" "def run" ./src # 打印匹配行的前 2 行和后 5 行,定位异常上下文 grep -n -B 2 -A 5 "Traceback" app.log # 扩展正则同时匹配多个关键词,输出最后 20 条 grep -E "ERROR|FATAL" app.log | tail -n 20-r让 grep 进入递归模式,--include限定文件类型,在代码库里找函数定义或配置项时比拿编辑器全局搜索更快。-B和-A分别表示匹配行之前和之后的上下行数,看异常堆栈时必须带上,否则只看到一行报错,看不到调用路径。-E启用的扩展正则支持|多选,一次匹配多个关键词比写多条 grep 再合并更清爽。
grep 与管道配合时需要留意缓冲问题:grep在输出到终端时是行缓冲,但输出重定向到管道或文件时变成块缓冲,tail -f实时追加日志时会出现“日志已经刷了很多,grep 这边半天没动静”的现象,这个问题在第 5 章的避坑部分会展开讲。
3.2 sed:流式替换与原地修改
sed最常见的两件事是替换和按行范围打印。它不加载整个文件到内存,而是逐行处理,所以对几百 MB 的大日志文件也能保持很低的资源占用。这个特性决定了它比编辑器更适合在批量环境里改配置。
# 替换 nginx.conf 中的 IP,同时备份原始文件 sed -i.bak 's/192.168.1.10/192.168.1.20/g' nginx.conf # 只打印第 10 到 20 行,快速查看某段日志 sed -n '10,20p' app.log # 删除空行,清洗 hosts 或配置文件 sed -i '/^$/d' hosts.txt-i.bak的意思是原地修改并生成.bak备份,这个备份是批量替换的后悔药——很多次我替换完才发现正则写错了,靠.bak一行命令就恢复了现场。不加g时 sed 只替换每行第一个匹配,加了g才是全局替换,这个细节经常被忽略。-n配合p的组合只有匹配和指定范围才打印,不加-n时 sed 默认会把所有行都打印出来,输出会混入大量无关内容。
用 sed 修改生产配置时,我的建议是三层保护:先grep -n确认目标内容存在,再执行替换,替换完立刻用grep验证结果。顺序执行三条命令比直接把-i写进一步操作要稳妥得多。
3.3 awk:按列统计的日志分析利器
awk 适合把日志里的一行拆成多列,再做统计和条件过滤。默认按空白(空格或 Tab)分割,这个行为在访问日志上直接可用。
# 打印访问日志第一列(通常是客户端 IP)和最后一列 awk '{print $1, $NF}' access.log # 按第 9 列(HTTP 状态码)统计请求数量,按次数降序排列 awk '{count[$9]++} END {for (code in count) print code, count[code]}' access.log | sort -rn # 求第 3 列的数值总和 awk '{sum += $3} END {print sum}' data.txt # 带条件过滤,只处理第 4 列大于 1000 的行 awk '$4 > 1000 {print $1, $4}' data.txt$NF表示当前行的最后一个字段,NF本身是字段数量,这两个变量在列数不固定的日志里很好用。count[$9]++用数组做计数器,END块在所有行处理完后执行,最终循环打印每个状态码的出现次数。awk 默认按连续空白分割,如果字段以逗号或竖线分割,需要-F指定,例如awk -F',' '{print $1}',这个参数常被忽略。
awk 和 sed 的分工也很清晰:sed 擅长按行做替换和删除,awk 擅长按列做统计和条件过滤。遇到“找出错误日志最多的 IP”这类需求,grep先过滤出错误行,再管道给awk统计第三列,两行命令就能完成原本需要在编辑器里折腾半天的分析。
4. 进程、资源与日志:把排查链路串成一条命令
4.1 ps 与 top:定位 CPU 与内存消耗者
服务变慢、负载升高这类问题,第一步一定是找到谁在消耗资源。ps查看的是命令执行瞬间的进程快照,适合做一次性的状态采集;top是持续刷新的动态视图,适合盯着某个进程看变化。
# 查看所有进程并按 CPU 使用率降序排列 ps aux --sort=-%cpu | head -n 10 # 查看与某服务相关的进程 ps -ef | grep mysqld | grep -v grep # 交互式查看;top 里按 P 按 CPU 排序,按 M 按内存排序 topps aux --sort=-%cpu中aux里的x会列出所有进程,包括没有终端控制的后台进程,--sort后面加负号表示降序。head -n 10取前 10 行,第一眼就能看到最占用 CPU 的进程。ps -ef | grep是查找特定进程的经典写法,末尾的grep -v grep用来过滤掉 grep 进程自己,不加这一节结果里会混入一条无关记录。top 进入交互模式后,按大写P键按 CPU 排序、按M键按内存排序,按k可以输入进程号直接发信号,适合在终端里快速处理反应缓慢的进程。
4.2 free、df、du:判断资源边界
内存和磁盘是 Linux 服务最常见的瓶颈。free、df、du三个命令分别回答“内存还剩多少”“磁盘分区还剩多少”“哪个目录占了多少”三个问题。
# 人类可读单位显示内存总量与剩余 free -h # 查看挂载点分区占用和文件系统类型 df -hT # 查看当前目录下各子目录的占用,按大小倒序 du -sh */ | sort -rh | headfree -h里的 used 列包含了文件缓存(cache),这部分内存在内存紧张时会被内核自动回收,因此不能直接用 used 判断内存是否真的不够。真正需要关注的是可用量,也就是 available 列。df -hT的-T显示文件系统类型,判断某个目录是不是网络存储时很有用。du -sh */只统计当前目录下一级子目录的大小,管道给sort -rh后就能一眼看出哪个目录占空间最多。
有一个常见误用:df看某个目录的占用很小,但服务依然报磁盘满。这种情况通常是有进程打开了已被删除的文件,文件句柄还存在,占用的空间没有释放。用lsof | grep deleted找占用句柄的进程,重启或让它重新打开文件后空间才会回来,这个坑在清理日志时特别常见。
4.3 把命令组合成一条排查链路
单条命令解决的是单一问题,真正的高效是把命令用管道和变量串起来。日志实时跟踪和进程监控是两个典型的组合场景:
# 实时跟踪日志中的 ERROR,并保持行缓冲输出 tail -f app.log | grep --line-buffered "ERROR" # 获取指定服务的进程号,再进入 top 的定向监控 pid=$(pgrep -f "server.jar") top -p "$pid"第一条命令里tail -f持续输出日志,grep --line-buffered保证新日志到达后立即刷新而不是攒在缓冲区里,这在排查线上问题时能帮助实时捕捉错误出现的时间点。第二条命令用pgrep -f按完整命令行匹配拿到进程号,top -p只监控这一个进程,避免在有几十个进程的机器上找不到目标。注意pgrep -f "server.jar"的匹配范围是完整命令行,如果机器上有多个相同参数的服务,需要用更精确的关键词区分,否则拿到的进程号可能不是你想盯的那一个。
5. Linux 命令避坑指南:5 个最容易翻车的现场
5.1 rm -rf 加空变量:差点删掉整个用户目录
现象:脚本执行rm -rf $dir/,由于$dir未赋值,命令实际变成了rm -rf /或rm -rf ~等超出预期的路径。
原因:变量在脚本执行时未被正确初始化,或者前一步的赋值命令失败但脚本没有退出,导致空变量继续参与后续命令。这是 Linux 运维里后果最严重的经典事故,很多人第一次遇到时都在测试机上,但这习惯用在生产环境就是事故。
解决:脚本开头加set -u让未定义变量直接报错退出;删除前打印要删除的路径人工确认;更稳妥的做法是给变量提供默认值再用[ -n ]判断非空:
#!/bin/bash set -u target="${DELETE_DIR:-/data/backup}" [ -n "$target" ] && rm -rf "$target"set -u是脚本保护的第一道防线,未定义变量出现时立即终止执行。${DELETE_DIR:-/data/backup}是参数展开语法,前半部分是变量名,:-后面是未定义时使用的默认值。最后一行[ -n ]再确认一次非空,三层保护把空变量导致的误删概率降到最低。
5.2 tail -f 管道 grep 后没有实时输出
现象:执行tail -f app.log | grep ERROR后,新日志一直在刷新但终端没有任何输出,过一段时间突然涌出一大段。
原因:grep 在输出到管道而不是终端时不再使用行缓冲,改成由系统决定何时刷新内核缓冲区,导致数据攒在缓冲区里没有立即显示,在交互排障场景极其误导。
解决:给 grep 加--line-buffered强制行缓冲:
tail -f app.log | grep --line-buffered "ERROR"这个参数只影响 grep 的输出缓冲策略,对匹配逻辑没有影响。在脚本里处理实时日志流时也建议带上,不只是终端使用,避免在计划任务里产生延迟输出。
5.3 文件名带空格和通配符
现象:循环复制日志时,for f in *.log; do cp $f /backup; done遇到my app.log这样的文件名,变量$f被分词拆成my和app.log,cp 报错,文件被遗漏。
原因:shell 对未加引号的变量引用会执行单词分割,文件名里的空格成为天然的分隔符。默认行为在大多数时候无害,但遇到带空格的用户文件名就翻车。
解决:统一给变量加双引号;批量操作文件名用find -print0配合xargs -0处理:
find /data -name "*.log" -print0 | xargs -0 -I {} cp "{}" /backup/-print0让 find 用空字符而不是换行分隔文件名,xargs -0按同样的分隔符读取,空格、换行、特殊字符都不用再担心。-I {}定义一个替换符,花括号位置会被每个文件名逐一替换,后续的cp命令中的双引号保护了目标名中的空格。相关的还有rm、mv,只要是批量处理文件名,统一遵循这个写法就不会出错。
5.4 sudo 也改不动的文件
现象:root 用户用 vim 修改配置文件,提示只有读权限,写入失败;检查属主和权限都正常。
原因:两种情况最容易被忽略——文件设置了 immutable 扩展属性(chattr +i),任何写入都会被拒绝,连 root 也一样;或者文件所在的分区以只读方式挂载,整块磁盘都无法写入。
解决:先用lsattr查看扩展属性,再用chattr -i去掉不可修改标志;用mount检查挂载参数:
lsattr /etc/some.conf chattr -i /etc/some.conf mount | grep ' ro 'lsattr输出的i标志就是 immutable 的迹象。chattr -i去掉后文件即可写。mount | grep ' ro '里的ro表示只读挂载,如果命中了这一项,说明是文件系统层面只读,比如异常关机后系统自动以只读模式挂载,这时要先确认磁盘状态再重新挂载,不要强行写入。先分清是文件属性还是挂载层面的问题,再决定下一步。
5.5 CRLF 换行导致脚本在 Linux 上报错
现象:从 Windows 环境保存的脚本放到 Linux 上执行,报/bin/bash^M: bad interpreter或出现$'\r': command not found。
原因:脚本在 Windows 环境编辑保存后,行尾是 CRLF(\r\n),Linux 只识别 LF(\n),\r被当成命令内容的一部分,解释器路径和每一行末尾都混入了回车字符。
解决:用 sed 或 dos2unix 转换换行符:
sed -i 's/\r$//' script.sh # 或者 dos2unix script.shsed -i 's/\r$//'的原理是只删除行尾位置的\r,不影响文件正文里的其他内容。dos2unix 是更专用的工具,处理批量文件更方便。这个坑也可以通过编辑器的设置从源头避免:文本类文件统一把换行符设为 LF,不管当前系统是什么环境。习惯后这变成一条经验:拿到外来脚本先跑一条file script.sh看一眼编码和换行信息,再决定直接执行还是先转换。
6. 把常用命令沉淀成自己的诊断习惯:一个快速检查脚本
前几章的命令单独看都不难,但真正能提升效率的做法是把它们组合成一套自己的检查流程。我习惯在每个服务器上放一个简短的健康检查脚本,里面是前面命令的组合——磁盘、内存、进程、日志一次扫完,排障时先跑一遍,再决定下一步往哪个方向深挖。
#!/bin/bash set -u echo "=== 磁盘使用 ===" df -hT | grep -v tmpfs echo "=== 内存使用 ===" free -h | head -n 2 echo "=== CPU 占用前 5 的进程 ===" ps aux --sort=-%cpu | head -n 6 echo "=== 最近 20 条 ERROR 日志 ===" tail -n 500 app.log 2>/dev/null | grep "ERROR" | tail -n 20这个脚本把第 4 章的核心检查项集中起来,set -u防止变量问题,grep -v tmpfs过滤掉虚拟内存文件系统的显示,避免刷屏,2>/dev/null保证日志文件不存在时脚本不会中断。跑出来的结果不需要全部看懂,重点是快速得到四个维度的概览:磁盘快满了吗、内存紧不紧张、哪个进程在吃 CPU、日志里有没有 ERROR。
除了脚本,我还会用 alias 固化两个最高频的命令,比如alias ..='cd ..'和alias grep='grep --color=auto',写在 shell 的 rc 文件里。别小看这两条,--color=auto在高亮显示匹配内容时,长日志里找错误信息一眼就能圈定范围。
我之前没有把这些沉淀下来时,每天排障都是东敲一条西敲一条,后来在一个通宵排查的晚上,猛然发现自己有一半时间浪费在重复输入相同的命令组合上。那之后我开始建脚本、加注释、把每次踩坑的解决方式写进检查清单里。现在面对一台陌生的服务器,拿起这个脚本先跑一圈,问题基本就浮出水面了。希望帮到你。
本文还有配套的精品资源,点击获取