☰
Linux命令实战:日志排查、进程管理、网络诊断与磁盘清理
2026/10/16 7:05:14 网站建设 项目流程

刚把一份基础命令清单翻完,多半已经会用ls、cd、cp、mv了。可真正坐上一台服务器去处理问题,面对日志、进程、端口、磁盘这些实际状况时,还是会卡住:命令都认识,就是不知道什么时候该用哪个、怎么串起来用。这篇就是来补这层"从认识命令到会用命令"的过渡。我把日常排查问题真正高频使用的那批 Linux 命令整理成第二册,每条都放到实际场景里讲,不搞大全式罗列。适合刚入门想开始独立处理服务器问题的朋友,也适合想系统补齐命令短板、看看别人怎么组织排查思路的开发者。

先说清楚这篇的定位:内容不追求命令数量,追求的是组合方式。文本处理、进程管理、网络诊断、磁盘传输、shell 效率这五块,基本覆盖了日常百分之八十的操作需求。每块下面讲的都是我在真实环境里反复用到的写法,附上踩过的坑和习惯,照着敲就能直接干活。

1. 看完入门列表之后,为什么上手还是卡壳

1.1 命令列表和真实排查之间,差的是场景感

我见过不少新人,手里一份命令清单,每个命令都能念出来,常见参数也能说出几个,但一遇到实际问题就不知道往哪儿套。原因是清单只告诉你某个命令能做什么,没告诉你在什么契机下会想起它。比如你知道grep能按关键字筛文本,可实际排查时,你不会平白无故去想"我要在日志里 grep 一下"——你得先知道服务器出问题了、日志在哪、报错长什么样,才会走到下一步。

场景感就是这条链路:异常现象 -> 怀疑方向 -> 找到命令 -> 分析输出。第二册里每个命令,我都会尽量用这条链路去讲,而不是只列参数表。

1.2 本文覆盖的命令板块与本篇适合的读者

这篇假设你已经能熟练使用最基础的文件操作和权限命令,所以不再重复ls、chmod这些内容。下面是一张快速导览表,先建立整体地图,后面每一节再展开:

场景主要命令典型用途
文本处理grep、sed、awk、find查日志、批量改文本、统计字段
进程资源uptime、top、ps、kill、nohup定位高占用、管理后台任务
网络排查ping、ss、curl、nc连通性、端口、接口问题
磁盘传输df、du、tar、rsync容量排查、打包、增量同步
Shell 效率history、alias、管道组合减少重复击键、批量统计

适合三类人:刚学完基础命令想进阶的;需要定期登录服务器处理问题的开发或运维朋友;想建立自己专属命令手册、而不是不断翻收藏夹的人。文章里的命令在常见发行版默认安装的前提下基本都能跑通,个别命令如果系统精简过没装,用对应发行版的包管理器补齐就行,比如apt install procps net-tools dnsutils或 yum 下对应的包。

2. 文本处理四件套:grep、sed、awk、find 各干各的活

2.1 grep:查日志不能只会一个裸 grep

很多人查日志的第一反应是grep 'error' app.log。这没问题,但碰到几万行甚至上千万行的日志时,裸 grep 会刷屏刷到你怀疑人生。而且日志里常见的是笼统错误关键字命中一堆无关行。我的几个固定习惯是这样的:

# 先看日志规模,再决定怎么查 wc -l app.log # 多关键字用扩展正则 -E,比一长串 -e 更清爽 grep -E "ERROR|Exception|Timeout" app.log # 只要命中行数,用 -c 或再套 wc -l grep -c "ERROR" app.log # 只要文件名,用 -l 在目录里递归找 grep -rl "关键字" /var/log/ # 看命中行前后的上下文 grep -E "ERROR|Timeout" -A 5 -B 2 app.log | tail -n 80

这里最容易被忽略的是上下文参数。定位异常原因时,只看命中那一行往往不够——错误之前的日志状态、之后的堆栈信息才是关键。我处理线上问题时几乎每次都带-A和-B,比如 Web 服务连续报超时,grep -E "502|timeout|ERROR" -A 5 -B 2 access.log | tail -n 80,先限定范围再看上下文,比直接拉全量日志直观得多。

另一个细节:日志大时别cat 文件 | grep,直接让 grep 读文件本身就行。grep 自己会逐行扫描并处理缓冲,中间多一层 cat 纯属浪费。另外 grep 默认走基础正则,.、*、[]这些字符的行为和 Perl 正则不完全一样;不确定时直接用-E,少踩转义的坑。

2.2 sed:改配置文件时的"就地替换"要小心 -i

sed 在我这里主要干三件事:按行范围打印、替换文本、删除指定行。其中替换是使用频率最高的场景:

# 预览替换结果,不改文件 sed 's/old_value/new_value/g' config.ini # 确认没问题后,加 -i 直接改原文件 sed -i 's/old_value/new_value/g' config.ini # 打印指定行范围 sed -n '100,200p' config.ini # 删除包含关键字的行 sed '/debug/d' config.ini

-i这个参数我一直怀有敬畏心,因为原地修改没有撤销。曾经有一次批量改配置时,替换表达式写错,结果把文件里一类本不该动的字段全改了,只能靠备份恢复。从那之后,我的流程固定在两步:第一步去掉-i,把结果重定向到另一个文件或者直接看终端输出;第二步确认替换效果无误,再重新执行带-i的命令。

还有一个小技巧:替换路径时,分隔符不一定要用/。路径里全是斜杠,写起来要疯狂转义,改用|或#做分隔符会舒服很多,比如sed -i 's|/usr/local|/opt|g' app.conf。

2.3 awk:按列切割之后,统计就变成一行事

awk 的核心是列处理。默认按空格或 Tab 分隔,每行自动分成$1、$2这样的字段,$0是整行。我常用的几种写法:

# 取指定列 awk '{print $1, $3}' server.log | head -n 20 # 指定分隔符,比如按逗号处理 CSV awk -F, 'NR > 1 {print $2, $5}' sales.csv # 过滤行,比如第四列数值大于 1000 的 awk '$4 > 1000 {print $1, $4}' monitor.log # 统计求和,比如累加所有行的第三列 awk '{sum += $3} END {print sum}' number.txt # 取每行最后一列,用 NF 变量 awk '{print $NF}' server.log

awk 之所以比 cut 好用,在于它不只是切列,还能做条件判断、累加、格式化输出。我最常用的统计场景是分析访问日志:日志格式通常第一列是来源 IP,我想统计访问量排名前十的 IP,一条管道就出来了:

awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -n 10

拆开看:awk 取第一列,sort 排序让相同 IP 相邻,uniq -c 计数并去重,sort -rn 按次数倒序,head 取前十。很多看起来复杂的统计需求,最后都能归成这种"取列 -> 排序 -> 去重计数"的管道组合,没必要上专门的数据分析工具。

2.4 find + xargs:批量清理文件的完整链路

find 是文档和日常使用差距最大的命令,因为它的能力密度很高。我常用的维度包括文件名、类型、大小、时间:

# 按名字找 find /var/log -name "*.log" -type f # 按修改时间找,比如 7 天前改过的 find /var/log -name "*.log" -mtime +7 -type f # 按大小找 find /data -type f -size +500M

find 的-exec可以直接在结果上执行命令,比如find ./tmp -name "*.bak" -type f -exec rm -f {} \。但文件量大时,我更推荐配合 xargs 使用。原因是 xargs 会分批传递参数,不会出现 "Argument list too long" 的报错。生产环境某个目录下堆积几十万个文件时,直接把 find 结果传给 rm 会报参数过长,xargs 按批次处理就没有这个限制。

# 删除 30 天前的日志,注意 -print0 和 -0 配对 find /data/logs -name "*.log" -mtime +30 -type f -print0 | xargs -0 rm -f

-print0让 find 用空字符而不是换行分隔结果,xargs -0按同样规则读取。这样即使文件名里有空格或特殊字符,也不会被错误拆分成多个参数。涉及删除的命令,我会先跑一遍不带删除动作的版本看看结果列表,或者把 xargs 后面的命令改成echo,确认参数传给谁、顺序对不对,再真正执行删除。

3. 进程和资源问题:从 load 高到决定 kill 的排查链路

3.1 先看负载再看进程,别一上来就 top 翻屏

接到"机器变卡"的反馈,我一般先敲uptime,而不是直接top。uptime 一行里包含当前时间和三个负载均值:1 分钟、5 分钟、15 分钟的平均负载。这里有个常见的误解:load 不是 CPU 占用百分比,而是运行队列里的任务数。粗略判断时,要和 CPU 核数对比。比如 4 核机器,load 长时间在 4 以上,说明任务排队明显;如果 1 分钟的值比 15 分钟高很多,说明压力是刚刚起来的,可能是瞬时流量或者某个定时任务;反过来 15 分钟持续高位,说明问题已经存在一段时间了。这个时间维度能帮你快速判断是偶发还是慢性。

3.2 CPU 与内存占用:ps 排序比肉眼盯 top 更靠谱

确认资源占用时,我用 ps 比 top 更频繁。top 是交互式动态刷新,适合人眼观察;ps 是静态快照,配合管道筛出想要的行,适合记录、执行后处理。两条最常用的命令:

# CPU 占用最高的十个进程 ps aux --sort=-%cpu | head -n 10 # 内存占用最高的十个进程 ps aux --sort=-%mem | head -n 10

ps aux输出里的字段要说两句:%CPU和%MEM是进程占用的比例,VSZ是虚拟内存大小,RSS是实际占用物理内存的近似值。新手常被 VSZ 吓到,看到一个进程虚拟内存好几个 G 就以为内存爆了,其实日常判断内存主要看 RSS。STAT字段里出现 D 表示不可中断的等待,Z 就是僵尸进程,后面会专门讲。

定位某个可疑进程时,我更习惯查它的启动时间和完整命令行。比如某个进程 CPU 一直 100%,先用ps -fp <PID>看启动时间和的完整命令路径,再用ls -l /proc/<PID>/cwd看它的工作目录,ls -l /proc/<PID>/fd看它打开了哪些文件。这一套下来,基本能判断这个进程是正常任务还是被人为启动的异常任务,再决定要不要处理。

3.3 僵尸进程和信号:kill -15 与 kill -9 的时机

僵尸进程(STAT 里的 Z)是最容易让人误操作的坑。僵尸进程是已经结束、但还没有被父进程回收的进程。它本身不占 CPU 也不占内存,但会留在进程表里。最关键的一点:不能用kill -9清掉僵尸进程,因为内核保留它就是为了让父进程来收尸。正确做法是找到它的父进程(PPID),ps -ef或ps -o pid,ppid,stat,cmd都能查到父子关系,然后重启或结束父进程。

kill 信号的时机也值得单独讲。默认的kill <PID>发送的是 TERM(15 号信号),给程序一个机会去做收尾处理、释放资源。kill -9是 KILL(9 号信号),内核直接结束进程,程序没有任何机会清理。很多服务在结束时要落盘缓存、关连接、写状态,直接 -9 容易留下脏数据。我的顺序是:先kill <PID>,等几秒看看进程是否退出;确实没反应,再上kill -9 <PID>。

信号数值用途
TERM15默认,请求优雅退出
KILL9强制结束,不可被捕获

3.4 后台运行与接管会话:nohup、bg、fg 的一次完整实践

后台运行是新手最常翻车的地方。很多人这样做:在终端里执行python3 long_task.py &,然后关掉终端,回来发现进程没了。原因是终端会话结束时,一般会给它的子进程发 SIGHUP 挂断信号。解决办法是结合nohup运行,或者用disown把进程移出当前 shell 的作业表。

我实际常用的写法:

nohup python3 long_task.py > task.log 2>&1 &

拆开解释:nohup让进程忽略挂断信号,退出终端也不会掉;>把标准输出重定向到文件;2>&1把标准错误也合并到同一个文件,否则报错可能只出现在终端里,进程后台跑完你什么都看不到;最后的&表示放入后台。

如果想在单个终端里管理多个任务,Ctrl+Z可以挂起当前前台进程,bg把它放到后台继续跑,fg再拉回前台,jobs列出当前终端的作业。这套交互在高频实验时会用到,但真正要长时间跑的任务,我还是直接 nohup + 日志文件,省得惦记终端开关。跑的过程中想看进度,再来个tail -f task.log就好。

4. 网络排查四连:ping、ss、curl、nc 怎么组合

4.1 连通性先看 ping,但别把 ping 当全部

排查网络问题的第一条线通常是 ping:ping -c 4 hostname,-c控制发送次数,-i 1控制间隔。看 rtt 时间可以判断延迟,看丢包率可以判断链路稳定性。但如果 ping 不通,先别急着下"网络断了"的结论。我碰到过的典型情况是目标机器禁了 ICMP,防火墙直接丢弃 ping 包,服务本身完全正常。所以 ping 只说明三层的连通情况,不是最终结论。

需要注意的另一面是:ping 通了也不代表业务可用。应用层的问题,比如 Web 服务没起来、数据库端口没开,ping 根本测不出来。所以 ping 通过之后,下一步通常要落到端口和连接状态上。

4.2 端口和连接状态:ss 一次看透

以前大家习惯用 netstat,现在我更推荐 ss。它直接读取内核 socket 信息,速度快,参数也好记。最常用的是看监听端口和对应进程:

# 查看所有 TCP 监听端口和占用进程 ss -tlnp

拆开看:-t只看 TCP,-l只看监听状态的 socket,-n不解析主机名和端口名,直接显示数字,-p显示进程信息。服务启动时报端口被占用,第一反应就应该是ss -tlnp | grep 8080,它会直接告诉你哪个进程 PID 占着这个端口。

看连接状态和连接数也有固定用法:

# 查看所有 established 连接 ss -tan | head -n 30 # 粗略统计各种连接状态数量 ss -tan | awk '{print $1}' | sort | uniq -c

排查"连接数异常升高"时,通常要看两个方面:一是谁在大量建立连接,二是连接状态集中在 ESTABLISHED 还是 TIME_WAIT。我以前掉进过一个坑:单看 ss 输出觉得某个 IP 连接多,以为是被攻击,后来发现是本地服务配置了错误的 keep-alive 参数,连接迟迟不释放。当时把它们从异常状态里区分出来的,就是按对端地址和状态同时做聚合统计。

4.3 curl 测接口:从响应头到超时参数

curl 是命令行里处理 HTTP 问题的主力。几个我离不开的参数:

# 只看响应头,快速判断状态码和响应头字段 curl -I http://127.0.0.1:8080/health # 响应头加 body 一起看 curl -i http://127.0.0.1:8080/health # 详细过程,适合定位卡在哪一步 curl -v http://127.0.0.1:8080/health # 带超时 curl --connect-timeout 5 --max-time 15 http://127.0.0.1:8080/health # 发送 JSON curl -X POST -H "Content-Type: application/json" -d '{"key":"value"}' http://127.0.0.1:8080/api

接口超时是我排查最多的一类问题。curl -v的输出能清楚显示解析 DNS 用了多久、建立 TCP 连接用了多久、发出请求后等待响应用了多久。解析域名很久,是 DNS 问题;connect 很久,是网络路径问题;请求发出后迟迟收不到响应,多半是后端服务处理慢。有一次测试环境接口偶发超时,curl -v 看到每次 connect 都要花好几秒,查下去发现是测试机器上 IPv6 配置有问题,解析到 IPv6 地址后连接失败,回退 IPv4 才成功,白白浪费了时间。

4.4 nc 做端口探测与临时代理时的几个注意点

nc(netcat)在排查场景里的作用被很多人低估。最常用的端口探测是nc -zv host port:-z表示只探测不发送数据,-v输出详细信息。批量探测可以写个小循环:

for p in 80 443 8080 3306; do nc -zv -w 3 10.0.0.8 $p; done

-w 3是超时 3 秒,防止某个端口没响应时命令一直挂着。nc 还能做临时监听:nc -l 9000,在有测试环境需要验证数据是否打通时会很方便。

这里有三个注意点。第一,不同发行版自带的 nc 变体参数有差异,传统 nc 和 openbsd 版对-z、-w的支持不同,跨机器用之前先nc -h确认。第二,端口探测成功只代表端口开放,不代表服务健康。第三,nc 发出去的探测流量可能被安全策略拦截,内网环境也要遵守规范。

5. 磁盘容量与文件同步:df、du、tar、rsync 的使用习惯

5.1 容量告急时,df 和 du 要先配合起来看方向

收到磁盘告警,我一般分两步。先df -h看整体:哪个挂载点满、容量多少、用了多少、在哪个路径下挂载。重点不是看哪块盘大,而是看具体挂载点对应的目录。可能出现/只剩 5%,而/data还有 60% 的情况,解决方法完全不同。

第二步用 du 定位大头:

# 当前目录下各一级项目的总大小,按从大到小排 du -sh * | sort -rh | head -n 10 # 或者直接指定目录深度 du -h --max-depth=1 /var/log | sort -rh | head -n 10

du 首次扫描大目录会慢,因为要遍历所有子目录。生产环境谨慎在根目录直接du -sh *,如果某个子目录挂载了外部存储,会扫得特别久。我的习惯是:先拿 df 分清挂载点方向,再进具体目录用 du 逐层定位。找大文件则直接用 find,限制在同一文件系统内避免扫描到其他挂载点:

find / -xdev -type f -size +1G 2>/dev/null

-xdev表示不跨文件系统,2>/dev/null把权限不足的报错过滤掉,扫起来快很多。

5.2 tar 打包的几个高频参数和容易翻车的细节

tar 是打包压缩的基本功,但细节容易翻车。我常用的写法:

# 打包并压缩 tar -czvf back_$(date +%F).tar.gz /home/user/data # 解压到指定目录 tar -xzvf back.tar.gz -C /restore/dir # 打包时排除日志和缓存目录 tar -czvf back.tar.gz --exclude='*.log' --exclude='cache' /home/user/data # 先看压缩包里有什么,再决定是否解压 tar -tzvf back.tar.gz | head -n 20

参数记忆方法:c创建,x解包,z用 gzip 压缩,v显示过程,f后面跟文件名。三个坑要记牢:一是解压默认解到当前目录,可能覆盖同名文件,所以我习惯先-t列出内容看看;二是打包时用了绝对路径,解压出来会带着整套路径结构,可能落在你意想不到的地方;三是打包进文件列表里如果有特殊字符,路径含空格的文件也要注意加引号。

5.3 用 rsync 做增量备份,比整目录 cp 稳妥得多

本地复制目录可以用 cp,但跨机器、跨磁盘、要增量时,我更相信 rsync。最基本的写法:

# 增量同步,保留权限和时间戳,显示进度 rsync -az --progress /data/source/ user@remote:/data/backup/ # 精确同步:源端删除的文件,目标端也删 rsync -az --delete /data/source/ user@remote:/data/backup/

-a归档模式,保留权限、时间戳等元信息;-z传输时压缩;--delete会把目标端多余的文件删掉,实现两边完全一致。带--delete的命令我第一次用时加上了--dry-run,先看它会删哪些文件再真正执行,这个习惯保留到了现在。

还有一个必须强调的细节:源目录尾部斜杠的语义差异很大。rsync -a src/ dst是把 src 目录里的内容同步到 dst 下;rsync -a src dst则会在 dst 下面生成一个 src 子目录。我见过不止一次因为少写一个斜杠,把文件同步到多了一层目录的情况。

5.4 清理磁盘时我常用的三层检查顺序

磁盘清理建议按顺序来,避免一上来就乱删。第一层,df -h确定哪个挂载点告急。第二层,du定位目录层级找出最大目录。第三层,find找出大文件和过期日志。对日志类文件,先确认服务能继续写再处理。有些应用正写着的日志文件,直接 rm 是释放不出空间的——文件句柄还开着,空间要等句柄释放才归还。这种情况下更彻底的做法是重启服务,或者在写日志的应用层面做切割。

还有一类隐蔽情况:df显示没有空间,但du怎么也找不到大头。这时多半是有进程占着已删除的文件。用lsof +L1可以列出所有被标记为已删除但仍被打开的文件,或者翻/proc/<PID>/fd里指向已删除文件的符号链接。排查到这里,问题的答案往往不是"谁占了磁盘",而是"谁占着已经删掉的文件没放手"。

6. Shell 效率三板斧:history、alias、管道思维

6.1 让历史命令少打一半字:Ctrl+R、!!、!$

终端操作里,减少重复击键比死记更多命令更实在。history 查看历史命令,Ctrl+R反向搜索历史,按一次是最近一条,继续按继续往前翻。!!表示上一条命令,!$表示上一条命令的最后一个参数,!*表示全部参数。举个我常用的场景:

mkdir /var/tmp/backup cd !$

先创建目录,然后cd !$直接进到刚才创建的目录。类似的还有sudo !!:上一条命令忘了加 sudo,不必重新敲一遍,直接补上。这几个符号看着不起眼,在反复对同一路径、同一命令操作时能省一大半事。习惯Ctrl+A跳到行首、Ctrl+E跳到行尾、Ctrl+U删到行首、Ctrl+K删到行尾之后,改长命令也不再需要频繁按方向键了。

6.2 把高频命令固化成 alias 和简单函数

高频命令写成 alias 是提升效率最直接的方法。写进~/.bashrc,source ~/.bashrc生效。我机器上常驻的几条:

alias ll='ls -lh' alias grep='grep --color=auto' alias df='df -h' alias ports='ss -tlnp' alias mem='ps aux --sort=-%mem | head -n 15' alias big='du -h --max-depth=1 | sort -rh | head -n 10'

注意 alias 不能带参数处理,需要参数时我会直接写一个简单的 shell 函数,比如dlog() { tail -f "$1"; }就是一个只接受的日志路径、自动进入 tail -f 的快捷方式。这里有个细节:alias 对非交互式 shell 默认不生效,脚本里如果要用最好直接写完整命令,别指望 alias 兜底。

6.3 管道思维:一条命令解决统计问题的示范

管道的本质是把上一个命令的标准输出,作为下一个命令的标准输入。初学者最容易卡住的地方是,它们不知道"任何命令都可以被串起来"。想练这个思维,最典型的例子是统计访问日志里来源 IP 排名:

awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -n 10

awk 取出第一列,sort 排序让相同 IP 相邻,uniq -c 去重并计数,sort -rn 按次数倒序,head 取前十。每一步的输出都是下一步的输入。遇到多步骤需求时,先不要急着找专门的分析工具,试着把需求拆成"取字段、排序、去重、取前几"的管道,很多问题几分钟就能有答案。

6.4 几个我私藏的短命令组合

最后分享几个我现在还在用的组合式命令,属于那种不常被文档提及、但日常真正帮到我的:

# 快速看指定目录下占用磁盘最大的子目录 du -sh /var/log/* 2>/dev/null | sort -rh | head # 查看当前连接数排名靠前的来源端口 ss -tn state established | awk '{print $4}' | cut -d: -f1 | sort | uniq -c | sort -rn | head # 查看某个服务的启动进程和启动时间,排查服务反复重启 ps -eo pid,lstart,cmd | grep -E "app_server" | head

我现在的习惯是:任何一个命令组合,只要在一天内用过两次,就抽时间整理成 alias 或一个小脚本,写进自己的笔记文件里。这套方法比反复翻收藏夹里的命令大全有用得多——命令从来不是靠背会的,是在具体场景里反复用、不断调试补充,慢慢变成了自己的肌肉记忆。等积累到一定量,你会发现真正值钱的不再是"知道多少条命令",而是"遇到问题时能把它切分成哪几步、用哪些命令组合走出去"。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询