简介:「linux实战100例」是一份面向Linux初学者与运维开发人员的实例型学习资料,围绕100个经典代码案例组织内容,重点覆盖网络调用命令、Apache参数配置、Linux错误代码解析以及常见应用故障的排查与解决方法,适合希望通过动手实践巩固命令行操作、服务配置与问题定位能力的学习者。压缩包共204个文件,约40.19MB,主体为195个html页面,便于按知识点浏览与检索,另配3个pdf、少量zip/rar资料包及doc、exe补充材料,形成从命令说明到配置详解的参考结构。已有2180人学习,说明其在Linux入门与实战查漏方面具有一定参考价值。读者可从中获得功能调用过程的细致说明、典型实例的操作思路、服务参数配置要点以及针对常见报错的解决线索,适合作为日常运维查询和系统学习Linux的辅助材料。
1. Linux 实战100例:先别急着背命令,先把“现场”补齐
linux 实战100例这个资源,名字听着像一本命令速查表,真拆开更像一本场景剧本合集:它不按 man 手册的字母序排,而是把运维现场拆成一例一解,从日志里捞 Top IP 到磁盘写满后三分钟定位,每一例都带着“先看什么、再看什么”的顺序。适合两类人:刚学完基础命令、一上生产机就发怵的新手,以及干了几年但排查全靠直觉、想把手感整理成套路的老手。它解决的不是“不知道有这个命令”,而是“知道命令却不知道先敲哪个”。
2. 拆开这 100 例:案例颗粒度、演练环境与刷法
拿到一份案例集,最怕的是从上往下顺着敲一遍,敲完只记住了ls -l的输出长什么样。这一章先把案例按颗粒度分类,再搭一台可以随便破坏的演练机,最后给一个能落地的刷题节奏。这三件事做完,后面的内容才吃得进去。
2.1 三类颗粒度:单命令、组合管道、场景剧本
案例集里的 100 例并不是同一个难度层级。按我拆下来的经验,大致能分三层,三层对应的能力和复现成本完全不同:
| 颗粒度 | 典型例子 | 复现成本 | 真正练到的能力 |
|---|---|---|---|
| 单命令 | find按时间/大小/权限筛文件、ss看监听、stat看元数据 | 一分钟,随时可跑 | 认参数、认输出字段 |
| 组合管道 | awk+sort+uniq统计 Top N、find+xargs批量处理 | 需要先造样本数据 | 数据流思维、字段切分 |
| 场景剧本 | 磁盘写满、服务起不来、403、定时任务不执行 | 需要快照机 + 故意造故障 | 排查顺序、收敛思路 |
第一层最容易产生错觉:命令敲出来了,输出也对,就以为会了。实际上单命令的价值在于“认输出”,比如ss -lntp里Recv-Q不为 0 意味着什么,df -hT里-i和普通模式差在哪,这些细节在生产现场才是决定性的。
第二层是分水岭。很多人卡在“知道awk能切列,但不知道该切第几列”。案例集里的组合管道例子基本都基于固定格式的文本(访问日志、ps输出、/proc下的文件),练的是“先确认字段分隔符,再数第几列”这个动作。这个动作练熟了,后面看任何日志都不慌。
第三层才是真正值钱的部分。场景剧本类案例不是教你一条命令,而是给你一条路径:现象是什么、第一个命令敲什么、看到什么结果就换方向。这类案例必须配合可破坏的环境,在真机上试是要出事的。
提示:如果时间有限,优先把第三层吃透。前两层随时能查手册补,第三层的排查顺序查不到。
2.2 演练环境:一台可以随便破坏的快照机
场景类案例的第一步不是敲命令,而是准备一台“砸了不心疼”的机器。常见做法是虚拟机加快照,或者用容器起一个临时环境。虚拟机更适合练磁盘、分区、systemd这类碰内核状态的案例;容器起得快,但systemd、/proc的部分信息会受限,只适合练文本处理和权限。
我一般会先在演练机上建一个专用目录,把案例需要的样本数据一次性造好,避免每次都要临时拼测试文件:
# 建一个只用来"造破坏"的演练目录,和生产路径彻底隔离 sudo mkdir -p /lab/cases sudo chown "$USER":"$USER" /lab/cases cd /lab/cases # 造 200 个测试文件:供 find / xargs / 通配符相关案例使用 for i in $(seq 1 200); do printf 'case-%s\n' "$i" > "file_$i.log" done # 造一份假的访问日志:字段顺序对齐常见 combined 格式 for i in $(seq 1 500); do printf '10.0.0.%s - - [10/Oct/2024:13:%02d:00 +0800] "GET /a HTTP/1.1" %s 512\n' \ "$((RANDOM % 20 + 1))" "$((RANDOM % 60))" "$((RANDOM % 2 ? 200 : 503))" done > access.log ls | wc -l这段脚本干了三件事:建隔离目录、批量生成小文件、生成一份字段可预测的假日志。chown "$USER":"$USER"是为了后面练权限案例时不用一直sudo;seq 1 200的数量不要太大,两百个文件足够让find和xargs的输出有可读性;假日志里刻意混了200和503,是为了后面统计状态码比例时能看到明显差异,全是 200 的日志练不出手感。
快照策略也要提前想好。我的习惯是:装完系统、配好网络、建完/lab目录之后打第一个快照,标记为“干净态”。每练完一组破坏性案例(分区、fstab、systemd单元、sudoers),回滚一次。血泪经验是练fstab那组案例时没打快照,写错一行挂载参数,重启直接进救援模式,一晚上就没了。
注意:涉及分区、
fstab、grub、sudoers的案例,一律在快照机上做,回滚成本是几十秒,真机上就是几小时。
2.3 刷法与时序:先猜输出,再敲命令
案例集最容易浪费的地方,是把它当小说看。看的时候觉得“哦这个我会”,合上就忘。有效的刷法是给每一例加一个“预测”动作:读题之后先别敲,用纸或者注释写下“我猜输出会是什么样”,然后再敲,对比差异。差异出现的地方,就是你真正没掌握的地方。
节奏上我建议分三段,总量 100 例,三周左右:
| 阶段 | 案例范围 | 每天量 | 阶段目标 |
|---|---|---|---|
| 认输出 | 1–40 例 | 6–8 例 | 看到输出能立刻指出哪一列是关键字段 |
| 串管道 | 41–75 例 | 5 例 | 三步管道内拼出想要的结果 |
| 演剧本 | 76–100 例 | 2–3 例 | 从现象推到根因,路径不跑偏 |
第一阶段的 40 例基本都是单命令,别嫌简单,重点是把--help和man对着看一遍,尤其是find的-mtime、-perm、-newer这几个参数,参数含义记混了后面全是坑。第二阶段开始上管道,每一例都要求自己先写出字段位置再动手,awk '{print $1}'里的$1是怎么数出来的,必须能说清。第三阶段最慢,一天两三例就够,因为每一例都要经历“造故障 → 观察 → 收敛 → 回滚”四步,快不起来。
刷的过程中建一个自己的速查文件,只记“我踩过的”而不是“手册上有的”。比如“du -sh /*会跨挂载点,要加-x”“grep -r遇到二进制文件会打印乱码,加-I”,这类条目攒到三十条,比任何速查表都好用。
3. 高频案例抄作业:文本三件套、权限定位与服务托管
100 例里出现频率最高的三类,基本覆盖了日常八成的工作量:从文本里捞信息、判断“为什么访问不了”、把脚本变成一个能被托管的服务。这一章把这三类的典型解法展开,代码可以直接抄到演练机上跑。
3.1 文本三件套:grep 定位行,awk 切字段,sed 改配置
三个工具的分工要分清:grep负责“哪几行”,awk负责“第几列、怎么算”,sed负责“改成什么”。混着用没问题,但心里要有这个分工,不然写出来的管道自己第二天都读不懂。
先看统计类案例,这是案例集里出现最多的一类:
# 统计访问量 Top 10 的来源 IP awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -n 10 # 按小时聚合 5xx 数量:$4 形如 [10/Oct/2024:13:05:00,按冒号切第 2 段是小时 awk '$9 ~ /^5/ { split($4, t, ":"); print t[2] }' access.log | sort | uniq -c第一行拆开看:awk '{print $1}'取第一列(默认按空白切分,日志里第一列就是 IP),sort排序让相同 IP 相邻,uniq -c把相邻重复项合并并计数,sort -rn按数字倒序,head -n 10取前十。顺序不能换,uniq只认相邻重复,跳过sort直接uniq -c会得到一堆计数为 1 的行。
第二行的关键是字段位置。$9是状态码,$4是带方括号的时间串,split($4, t, ":")把它按冒号切成数组t,t[2]就是小时段。这里有个坑:如果日志时间格式不是方括号包起来的,字段位置会整体前移,$4就可能变成请求行。动awk之前先head -n 3 access.log确认格式,比事后 debug 省事。
再看改配置类案例。生产上改配置文件,最忌讳直接sed -i:
# 先看会被改到哪几行,确认匹配范围 grep -nE '^[[:space:]]*Listen[[:space:]]+80$' /etc/nginx/nginx.conf # 确认无误后再原地改,-i.bak 留一份后悔药 sudo sed -i.bak -E 's/^([[:space:]]*)Listen[[:space:]]+80$/\1Listen 8080/' /etc/nginx/nginx.conf # 改完做语法校验,别直接 reload sudo nginx -t-i.bak会在改之前生成一个同名.bak文件,这是最便宜的后悔药。正则里用^和$锚定整行,避免把注释行#Listen 80也改掉;[[:space:]]*保留原有缩进,配置文件的缩进乱了以后排查很痛苦。最后一步nginx -t是必须的,配置语法错了直接 reload 会把正在跑的服务带下去。
参数上还有两个细节值得记:sed -E开启扩展正则,省掉一堆反斜杠;grep -n输出行号,配合sed -n '12,20p'可以只改某一段。批量改多个文件时用grep -rl先列出文件清单,再套xargs sed -i.bak,比find -exec更可控。
3.2 权限与属主:一条 403 的完整定位链
“文件明明在,就是访问不了”是案例集里最经典的剧本之一。多数人的第一反应是chmod 777,这是典型的治标不治本。正确的顺序是从路径最外层往里看。
# 逐级列出路径上每一层目录/文件的权限、属主、属组 namei -l /var/www/site/uploads/2024/report.pdf # 以服务实际运行的账号身份,验证到底能不能读 sudo -u www-data test -r /var/www/site/uploads/2024/report.pdf \ && echo "readable" || echo "denied" # 看有没有 ACL 在捣乱(getfacl 比 ls -l 多出一层信息) getfacl -p /var/www/site/uploads/2024/report.pdfnamei -l是这条链上最值钱的命令,它把路径上每一层的权限一次性摊开。常见的 403 根因是“文件是 644,但中间某一层目录少了x位”——目录的x表示“可以穿过”,没有x就算文件本身可读,也进不去。这个知识点看十遍书不如namei -l输出一次。
sudo -u那行是排除法:以服务的真实身份去test -r,返回 denied 就说明问题在权限,返回 readable 就说明问题不在文件系统,往 SELinux、服务配置、上游转发去查。
getfacl用于兜底。有些环境用 ACL 给单个账号开过权限,ls -l看到的是+号,具体规则要看getfacl。ACL 和普通权限是叠加关系,排查时两边都要看。
修复动作要按最小权限来。目录给755、文件给644、属主改成服务账号,这三步能解决绝大多数问题:
# 目录补上 x 位,文件保持 644,属主交给服务账号 sudo chmod 755 /var/www/site/uploads /var/www/site/uploads/2024 sudo chmod 644 /var/www/site/uploads/2024/report.pdf sudo chown -R www-data:www-data /var/www/site/uploadschmod -R 777之所以危险,不只是安全问题。有些服务对权限过宽的文件会直接拒绝,比如密钥文件权限不是600就会被判定为不安全而拒绝加载,改完反而更糟。权限这组案例的正确练法,是在演练机上故意把某一层目录改成700、属主改成别的账号,然后只用namei和sudo -u两个工具把根因找出来。
3.3 systemd 托管:把脚本变成能自启、能重启的服务
案例集里有一组专门讲“脚本手动能跑,一关终端就死”。答案是别用nohup硬扛,写成systemd单元。这是从“会用命令”到“会交付”的分界线。
# /etc/systemd/system/demo-app.service [Unit] Description=demo app After=network-online.target Wants=network-online.target [Service] Type=simple User=appuser WorkingDirectory=/opt/demo Environment="APP_ENV=prod" ExecStart=/opt/demo/run.sh Restart=on-failure RestartSec=5 LimitNOFILE=65535 StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target几个参数值得逐个说清。Type=simple表示ExecStart启动的进程就是主进程,适合前台运行的脚本;如果程序自己会fork到后台,要用Type=forking并配PIDFile,配错了systemctl stop会停不干净。After和Wants一起写,保证网络就绪后再启动,只写After不写Wants时,如果目标单元没被其它服务拉起来,顺序保证就落空。Restart=on-failure只在非零退出时重启,RestartSec=5防抖动,避免程序启动即崩导致反复拉起刷日志。LimitNOFILE是文件描述符上限,高并发服务不设这个,跑一段时间就会遇到Too many open files。
写完单元文件后的动作是固定的四步:
sudo systemctl daemon-reload # 改了 unit 文件必须重载 sudo systemctl enable --now demo-app # 开机自启 + 立即启动 systemctl status demo-app --no-pager # 看 Active 和最近几行日志 journalctl -u demo-app -f # 跟踪日志,排错时盯着这个daemon-reload是最容易漏的一步。改完 unit 不重载,systemctl restart用的还是旧配置,会出现“我明明改了但没生效”的玄学现象。enable --now是enable加start的合并写法,省一条命令。
练这组案例时,建议故意制造三种失败:ExecStart路径写错、User写成一个不存在的账号、脚本里exit 1。然后只用systemctl status和journalctl -u把原因读出来。status输出里Process: ... status=203/EXEC表示执行文件不可执行或路径不对,status=217/USER表示账号不存在,这两个错误码记住,能省很多时间。
4. 现场取证三连:磁盘写满、端口占用、日志暴涨的排查顺序
这三个剧本在案例集里占了不小的篇幅,也是真实环境里最常被叫去处理的。它们的共同点是:现象很吓人,根因往往很小。区别在于排查顺序不能乱,顺序错了会白跑很多冤枉路。
4.1 磁盘写满:先分清是块满了还是 inode 满了
看到“No space left on device”,第一步不是删文件,是分清哪种满:
df -hT / # 看块使用率 df -i / # 看 inode 使用率 du -xh --max-depth=1 / 2>/dev/null | sort -rh | head -n 10df -hT带-T是为了看到文件系统类型,overlay、xfs、ext4在处理方式上不一样。df -i容易被忽略:小文件特别多的场景(缓存目录、会话文件、邮件队列)会出现块还剩很多但 inode 耗尽,此时删大文件完全没用,要删的是数量。du -xh里的-x表示不跨挂载点,不加这个参数会跑到/proc、/mnt下面去,输出一堆无关内容还慢。
定位到具体目录后,最常见的坑是“文件删了但空间没回来”:
# 找出被进程持有、但目录项已删除的文件 sudo lsof +L1 2>/dev/null | head -n 20 # 日志类文件正确的清空方式:保留 inode,只清内容 sudo truncate -s 0 /var/log/demo/big.loglsof +L1列出 link count 小于 1 的打开文件,也就是“已经rm了但进程还拿着句柄”。这类文件空间不会释放,直到进程退出或重新打开。解决方式两种:重启对应进程,或者用truncate -s 0清空(前提是还有目录项)。日志文件不要用rm删,用truncate -s 0或者: > file,前者更明确,后者更短,效果一样。
参数上还有两个细节:du和df结果对不上时,先查lsof +L1,再查挂载点是否被覆盖(有东西挂到了非空目录上)。df显示的空间是整个文件系统的,du只统计当前能看到的目录项,这个差值就是被删文件或者被覆盖目录占用的部分。
4.2 端口占用与进程假死:从端口反查到进程现场
“端口被占用”这类报错,正确做法是反查而不是猜:
# -l 监听态 -n 不解析 -t TCP -p 显示进程 sudo ss -lntp | grep ':8080' # 拿到 PID 后看它的启动时间、父进程、完整命令行 ps -o pid,ppid,etime,cmd -p 12345 # 看它实际用的是哪个工作目录、哪份配置文件 sudo ls -l /proc/12345/cwd /proc/12345/exe sudo tr '\0' '\n' < /proc/12345/environ | grep -iE 'CONF|ENV'ss -lntp比netstat快得多,-p需要 root 才能看到别人的进程。拿到 PID 之后,ps -o etime看运行时长很有用:如果这个进程已经跑了三个月,那它大概率是正常服务,你新起的那个才该换端口。/proc/PID/cwd是指向工作目录的软链,很多“配置改了不生效”的问题,根源是进程的工作目录和你想的不是同一个。/proc/PID/environ是启动时的环境变量快照,用tr '\0' '\n'转成可读格式后grep,能确认它加载的是哪套配置。
进程状态也要看。ps输出里D状态(不可中断睡眠)通常卡在 IO 上,kill -9都杀不掉,这时候要去看存储和内核日志;Z状态是僵尸,说明父进程没回收,杀它没用,要处理父进程。
停进程的顺序是有讲究的:先kill -TERM,等几秒,确认退出,再考虑kill -KILL。直接上-9会让进程没机会刷缓冲、没机会删锁文件,数据库类进程还可能损坏数据文件。案例集里专门有一例演示这个差别,值得动手复现一次:写个脚本捕获TERM信号打印一行再退出,对比-9的表现,印象会深很多。
4.3 日志暴涨:logrotate 配置与 journald 限额
日志把磁盘吃满,事后再清是下策,事前配置才是正解。文件类日志交给logrotate:
# /etc/logrotate.d/demo-app /var/log/demo/*.log { daily rotate 14 maxsize 200M missingok notifempty compress delaycompress copytruncate }逐项说明:daily按天切,maxsize 200M是保险丝——没到一天但超过 200M 也切,两个条件满足其一就触发,这是防止单日暴涨把盘打满的关键;rotate 14保留 14 份;compress压缩历史文件,delaycompress让最新一份不压缩,因为程序可能还在往里写;copytruncate适用于不支持重新打开日志文件的程序,先复制再清空原文件,代价是切换瞬间可能丢几行。如果程序支持USR1信号重开日志,用postrotate发信号更干净,不会丢行。
# 干跑一次,看它打算怎么切,不实际执行 sudo logrotate -d /etc/logrotate.d/demo-app # 强制切一次做验证 sudo logrotate -f /etc/logrotate.d/demo-app-d是 dry run,只打印不执行,配置写错时靠它发现问题。-f强制执行,用于验证配置是否真的生效,别在生产高峰期跑。
系统日志走journald,它有自己的容量控制,默认上限和所在发行版的配置有关,不设的话长期运行会稳定吃掉几个 G:
# 查看当前 journal 占用 journalctl --disk-usage # 立刻收缩到 500M sudo journalctl --vacuum-size=500M持久化配置在journald.conf里,SystemMaxUse=1G控制总上限,SystemMaxFileSize控制单个文件,改完systemctl restart systemd-journald生效。--vacuum-size是应急手段,治标;配置文件才是治本。这组案例的正确练法是在演练机上用dd或循环写日志把盘填到 90%,然后分别在“有 logrotate”和“没 logrotate”两种配置下观察一天,差别一目了然。
5. 避坑清单:这 5 个案例我建议你先看翻车记录再动手
案例集里有些例子看着简单,实操时翻车率极高。下面五条是我自己以及身边人真实踩过的,按“现象 → 原因 → 解决”写,动手前扫一遍能省不少时间。
5.1rm -rf拼变量:目录被清空的经典写法
现象:脚本里rm -rf /data/app/$DIR/执行后,/data/app/下的内容全没了,包括不该删的。
原因:$DIR为空或者没定义时,路径变成/data/app//,等于删掉整个目录。加上脚本里有set -e也没用,因为rm本身返回成功。
解决:三件事一起做——脚本开头set -u让未定义变量直接报错;用${DIR:?DIR is empty}强制非空;执行前先echo预览。
#!/usr/bin/env bash set -euo pipefail DIR="${1:?usage: cleanup.sh <subdir>}" TARGET="/data/app/${DIR}" echo "[dry-run] would remove: ${TARGET}" rm -rf -- "${TARGET:?}"${1:?}的冒号表示“未设置或为空都报错”,比${1?}严格。路径变量统一加双引号,防空格和通配符展开。--让rm停止解析后续参数,避免目录名以-开头时被当成选项。
5.2 在/tmp下跑服务:重启后文件凭空消失
现象:程序放/tmp下能跑,机器重启或者过一段时间后服务起不来,报“文件不存在”。
原因:/tmp在多数发行版上是tmpfs(内存盘)或带定期清理策略;systemd单元里如果开了PrivateTmp=true,服务看到的/tmp是独立命名空间,和你手动登录看到的不是同一个。
解决:可执行文件和配置一律放/opt或/usr/local下;临时文件放到/var/tmp或自建目录;确认 unit 文件里没有多余的PrivateTmp。
# 确认 /tmp 是不是内存盘,以及清理策略 findmnt /tmp systemctl show demo-app -p PrivateTmpfindmnt的输出里tmpfs就是内存盘,重启必丢。systemctl show能看到单元的最终生效属性,比翻 unit 文件可靠,因为还有 drop-in 目录里的配置会叠加。
5.3 用kill -9代替正常停止:锁文件与数据文件遭殃
现象:进程停不掉就用-9,之后重启报“端口已被占用”或者数据文件损坏。
原因:SIGKILL不可捕获,进程没机会执行清理逻辑——锁文件不删、缓冲不刷盘、子进程变孤儿。端口处于TIME_WAIT或者子进程还占着监听。
解决:先TERM再等待,最后才KILL;确认没有子进程残留;清理遗留锁文件前先确认没有同类进程在跑。
PID=12345 kill -TERM "$PID" for i in $(seq 1 10); do kill -0 "$PID" 2>/dev/null || break sleep 1 done kill -0 "$PID" 2>/dev/null && kill -KILL "$PID" || echo "graceful exit"kill -0只做存在性检查,不发信号,适合用来轮询。循环 10 次、每次 1 秒,给进程 10 秒的优雅退出窗口,这个时长对多数服务够用。
5.4 习惯性chmod -R 777:越改越连不上
现象:为了省事把目录递归改成 777,结果 SSH 免密登录失效,或者某个服务直接拒绝启动。
原因:部分程序对权限有强校验,密钥文件权限过宽会被判定为不安全而拒绝使用;目录加了w位还可能被其它账号篡改。
解决:按最小权限恢复——目录755、普通文件644、私钥600、.ssh目录700;改完用namei -l逐级复核。
chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys ~/.ssh/id_ed25519 chmod 644 ~/.ssh/known_hosts ~/.ssh/config namei -l ~/.ssh/authorized_keys改权限时不要用-R一把梭,.ssh下每类文件的正确权限不一样,递归会把该600的也变成644。
5.5 crontab 手动能跑、定时不执行
现象:命令行里执行脚本一切正常,加到crontab后毫无动静,日志里也看不到报错。
原因:cron的环境变量极简,PATH通常只有/usr/bin:/bin,脚本里用的python3、node、docker可能根本不在这个路径里;另外%在 crontab 里是换行符,命令里带日期格式化会被截断。
解决:命令全用绝对路径,脚本开头自己source环境,输出重定向到日志文件,%用\%转义。
# crontab -e SHELL=/bin/bash PATH=/usr/local/bin:/usr/bin:/bin 30 2 * * * /opt/demo/backup.sh >> /var/log/demo/backup.log 2>&1SHELL和PATH写在 crontab 顶部对所有条目生效,这比在每个脚本里硬编码更集中。>> ... 2>&1把标准输出和错误都落到文件,不然失败时连线索都没有。排查时先看/var/log/cron或者journalctl -u crond,确认任务到底有没有被触发,再区分是“没触发”还是“触发了但命令失败”。
6. 把 100 例压成一页 runbook:验证脚本与自检习惯
案例刷完不等于会用,中间差的是一层“验证”。我的做法是把 100 例收敛成一页纸的检查清单,每条只写三样东西:什么现象、第一个命令、判断标准。然后在演练机上用脚本把能自动验证的部分跑一遍,跑不通的就是没真会。
下面这个骨架可以在每次改完系统配置后跑一遍,输出一份体检报告:
#!/usr/bin/env bash # 系统体检:把案例里最常用的几项检查串成一次执行 set -uo pipefail echo "== 磁盘 ==" df -hT -x tmpfs -x devtmpfs | awk 'NR==1 || $6+0 > 80' df -i -x tmpfs -x devtmpfs | awk 'NR==1 || $5+0 > 80' echo "== 被删除但被占用的文件 ==" lsof +L1 2>/dev/null | awk 'NR>1 {print $1, $7, $NF}' | head -n 10 echo "== 失败的单元 ==" systemctl --failed --no-legend --no-pager echo "== 监听端口 ==" ss -lntp | awk 'NR>1 {print $4, $6}' | sort -uset -uo pipefail去掉了-e,因为体检脚本要允许某一项检查失败后继续跑完;pipefail保证管道中间出错时整体返回非零,不会被最后一个awk的成功掩盖。df那句用awk过滤使用率大于 80 的行,输出为空就说明没风险。--failed只看失败单元,--no-legend去掉表头,方便肉眼扫。
验证效果的标准也很简单:把同一条命令在故障前后各跑一次,两次输出必须有肉眼可见的差异。比如磁盘满的案例,修复前df -i的使用率接近 100%,修复后掉回个位数;端口占用的案例,修复前ss -lntp有两条记录抢同一个端口,修复后只剩一条。如果跑完看不出差异,说明这一例还没真正复现。
| 案例类型 | 验证方式 | 通过标准 |
|---|---|---|
| 文本处理 | 换一份格式相同但内容不同的日志重跑 | 结果仍正确,字段位置不变 |
| 权限问题 | 用sudo -u以服务身份访问 | 返回 readable 且服务能实际取到文件 |
| 服务托管 | 手动kill主进程后观察 | 5 秒内自动拉起,status显示新 PID |
| 磁盘问题 | 修复前后各跑一次df -hT和df -i | 使用率明显回落,被删文件条目消失 |
| 定时任务 | 临时改成每分钟执行一次 | 日志里有输出,无command not found |
表格里最有价值的是“文本处理”那一行。很多人练完案例只验证了当前这份样本,换个日志格式或者换个字段位置就崩。真正过关的标志是换数据源还能跑。
最后是一个习惯:所有涉及删除、权限、挂载、单元文件的操作,先在演练机上敲一遍,把输出贴到自己的 runbook 里,再上真机。从那以后我每次动生产机的配置,都强制走一遍“快照 → dry run → 校验命令 → 观察五分钟”这个流程,多花三分钟,少熬三个晚上。这份 linux 实战100例的资源我按场景分了目录,对着上面这套刷法从第一例开始敲,比自己从头翻手册快得多,希望能帮到你。
本文还有配套的精品资源,点击获取