简介:面向Linux学习者与开发者的实战案例合集,从100个最具代表性的编程实例切入,完整还原每个功能调用的参数、顺序与结果验证过程。内容覆盖网络调用命令、Apache参数配置、系统错误代码解析等高频主题,并针对服务无法启动、端口被占用、权限不足、配置文件报错等典型问题归纳了清晰的排查步骤与修复方法。资源包共204个文件,总大小约40.19MB,结构以195个HTML文档为主,打开浏览器即可对照代码和说明学习;配套3个PDF手册深化理论,2个ZIP与2个RAR压缩包提供可复用脚本和历史版本归档,1个DOC学习笔记与1个EXE电子书则适合在通勤或碎片时间补充背景知识。目前已有2180人学习下载,不少读者反馈案例贴近实战、排错思路可直接迁移。通过该合集可以系统梳理Linux编程中的调用链与配置项,既能逐例练习、随查随用,也能从错误代码入手快速定位系统故障,尤其适合从基础向进阶过渡的运维人员与后端开发者。
1. 从"会敲命令"到"能扛故障":linux实战100例值不值得逐条复现
很多做运维或刚转行 Linux 的人都有这种体验:常用命令背得滚瓜烂熟,top、ps、df、grep 张口就来,可真遇到磁盘被日志打满、服务半夜挂掉、定时任务不执行,还是得手忙脚乱翻半天资料。网上免费的 linux 文章一大堆,但大多是零散知识点,看完不解决实际问题,更别说应付面试题里那些「服务起不来你怎么排查」的追问。
「linux实战100例」这类案例集的价值,在于把常用命令、shell 脚本、故障排查整合成场景化的可复现步骤,不是命令大全的罗列,更像一本带答案的练习册。我的建议很直接:别急着背,把它当训练场,每周照做三五例,动手敲一遍,比读十篇教程有用。这份资源适合两种人,一是手里没有生产环境练手的新手,二是已经在做 linux 系统管理但想补脚本和故障排查短板的人。这篇笔记是我逐条复现后的经验拆解,从编排逻辑一路讲到最容易翻车的五个坑。
2. 先看懂100例的编排逻辑:命令、脚本、故障三类案例怎么串
拿到这份案例集,最忌讳的就是从头翻到尾当小说看。一百个案例看着多,其实编排路线很固定。按我自己的复现习惯,会先把目录扫一遍,把案例分成三类:命令型、脚本型、故障型。命令型案例学的是参数组合,脚本型学的是逻辑分支和循环,故障型学的是一套完整的排查路径。三类分开学,效率完全不一样。
举个直观的例子:同样一条grep,放在命令型案例里你可能只学会了grep -r递归搜索;放在故障型案例里,你会学会用grep "Failed password" /var/log/secure去定位暴力破解来源。同一个命令,目标不同,学到的深度完全不同。所以复现前先分类,是我觉得最值得抄走的第一步。
2.1 文件与目录操作:命令型案例的学法是「组合」
文件类案例通常占前二三十个,也是很多人觉得「太简单」直接跳过的部分。单条命令谁都会,实战考的是组合。比如排查 /home 目录被占满,直接看 df 不够,得逐步收窄。我一般是这么走的:
df -h du -sh /home/* find /home -type f -size +100M -exec ls -lh {} \;这里的关键点说三句。df -h确认哪个挂载点使用率接近百分之百,-h是 human-readable,用 G、M 显示单位。du -sh的-s是 summary,只输出每个目录的总大小,不看子目录明细。最后find把超过 100MB 的文件逐个列出来,-exec ls -lh {} \;对每个命中的文件执行一次列目录操作,{}是文件占位符。
这类案例复现的时候,我自己还会补一个动作:用stat看文件的修改时间,判断那个大文件是不是日志残留。日志类文件 mtime 一般很新,如果发现是个把月前的老文件占着空间,说明清理任务可能早就失效了。这个补充观察在后面排查故障案例时非常有用,建议你也养成这个习惯。
2.2 进程与服务管理:故障型案例的落脚点
故障案例里超过一半最终会落到进程和服务状态上,所以进程管理这条路必须先打通。现在新装系统几乎都是 systemd,systemctl是主命令,但老系统还在用service和chkconfig。案例集里涉及服务启动和守护的,我一般先确认当前环境是哪种 init 系统,再往下走。
systemctl status nginx if [ $? -ne 0 ]; then echo "nginx 服务异常,先看日志再决定是否重启" journalctl -u nginx --since "30 min ago" --no-pager | tail -n 50 fi这段脚本逻辑很简单:systemctl status nginx的返回值直接决定后面走哪个分支,$?拿到的就是上一条命令的退出码,0 是正常,非 0 是有问题。我一般不会在状态异常时直接 restart,而是先拉日志。journalctl -u nginx只看 nginx 这个 unit 的日志,--since按时间窗口过滤,--no-pager避免输出被分页卡住,tail -n 50只看最近 50 行。
这就是典型的故障型案例套路:先确认状态,再找原因,最后才操作。顺序反了,就变成瞎试,对经验的积累没什么帮助。我在虚拟机安装 linux 系统练手的时候,经常故意把服务搞挂再按这个顺序排,练熟了应变能力会强很多。
2.3 网络与日志:把现象变成证据
网络和日志这两块,新手最头疼,因为在本地没法直观看到效果。建议用虚拟机装 Linux 做实验,把ss、tcpdump、journalctl这几条链路反复敲熟。举一个最常用的组合:
ss -tlnp | grep :80 grep "Failed password" /var/log/secure | awk '{print $1}' | sort | uniq -c | sort -nr第一条命令里,ss比netstat更快更准,-t只看 TCP,-l只显示监听状态的端口,-n不做域名反解,-p显示占用进程的信息。一条就能看出 80 端口到底被谁占着,注意-p需要 root 权限。第二条是经典的日志统计管道:grep筛出失败登录记录,awk '{print $1}'取第一列 IP,sort排序,uniq -c统计每个 IP 出现次数,再sort -nr按数字倒序。攻击来源一眼就能看到。
网络类案例看的是端口和连接状态,日志类案例看的是时间和来源。把这两类命令组合练熟,100 例里大概三分之一可以做到不查资料直接复现。这里补一个路径细节:CentOS 系失败登录日志在/var/log/secure,Ubuntu 系在/var/log/auth.log,跨系统复现时记得替换。
2.4 脚本与自动化:案例集里最容易被低估的部分
100 例里脚本类案例往往是压轴部分,很多人只看前面的命令,把脚本全跳过,这个习惯很亏。脚本类案例的编排逻辑一般是:从单行命令开始,慢慢加 for 循环、if 分支、函数封装。比如批量重命名、批量分发公钥、一键部署环境,这类案例学完直接能迁移到工作里。
我复现脚本类案例时会做一件事:把每个脚本里出现的变量、循环、判断都标出来,然后问自己三个问题——这个变量如果为空会发生什么;这个循环如果遇到空目录会不会报错;这个判断到底在保护什么。三个问题问下来,脚本里大多数坑都能提前发现。这也是为什么我一直强调,脚本型案例不能只是复制粘贴跑一遍,要拆开理解,尤其是变量保护和空值处理,第 5 章我会专门讲血泪教训。
3. 照着复现五组高频案例:从单条命令到可复用脚本
第 2 章讲的是怎么分类,这一章是实际操作。我从 100 例里挑出复现价值最高的五组,覆盖磁盘、定时任务、批量分发、性能监控、权限管理,每一组都按「命令—参数—扩展」来讲。你能直接照敲,也能在工作里改一改复用。
3.1 磁盘占满排查:df、du、lsof 三板斧
磁盘占满是 linux 运维故障案例里的常客,嵌入式 linux 设备上尤其频繁,因为 flash 空间就那么点,日志一膨胀系统就卡。排查顺序我固定是 df 看分区、du 看目录、lsof 看文件句柄。
df -h du -sh /var/log/* lsof | grep deleted前两条和第 2 章思路一致,重点是第三条。lsof | grep deleted用来找「已经被删除但仍然被进程占用的文件」。这个场景很经典:日志被rm删了,但进程还握着文件句柄,空间不会释放,df 看还是满的。解决方式是重启对应进程或kill掉,让内核回收句柄。
我遇到过最典型的一次:磁盘满告警,du 扫描很久都找不到大文件,因为真正的空间被一个已删除的 .log 占着,lsof | grep deleted一抓一个准。从那以后我把这条命令写进了自己的排查清单,磁盘类案例我都会先补这一步。参数上不用加别的,默认输出文件路径加进程 PID,信息足够。
3.2 定时任务与日志切割:crontab 与 logrotate 的搭配
定时任务是脚本型案例里的重头戏。crontab -e编辑当前用户的定时任务,格式是五个字段:分、时、日、月、周。实战里最常用的是配合 logrotate 做日志切割。
# crontab -e 添加,每天凌晨 3 点执行备份脚本 0 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1# /etc/logrotate.d/nginx 配置示例 /var/log/nginx/*.log { daily rotate 7 compress missingok notifempty sharedscripts postrotate /bin/kill -USR1 $(cat /var/run/nginx.pid) 2>/dev/null || true endscript }第一个代码块里0 3 * * *是执行时间,分、时、日、月、周分别对应,>>追加日志,2>&1把标准错误也重定向进去,脚本出错时才不会静默丢消息。第二个代码块是 logrotate 的典型配置,daily按天切割,rotate 7保留 7 份,compress压缩旧日志,postrotate段执行的动作很关键——切割后通知 nginx 重新打开日志文件,否则 nginx 还会往里写旧文件名。
这里有个参数细节,notifempty表示日志文件为空就不切割,避免生成一堆空文件。missingok让文件不存在时也不报错。配套验证用logrotate -d /etc/logrotate.d/nginx做 dry-run,确认配置没问题再交给 crontab。
3.3 批量文件处理与分发:find、for、rsync
批量处理是 shell 脚本最实用的场景之一。最常见的需求是找出一批符合条件的文件,做重命名或者分发到别的机器。我常用的两个写法:
# 批量重命名 .txt 为 .md for f in *.txt; do mv "$f" "${f%.txt}.md" done# 把 /data 下的 .log 同步到远程备份机 find /data -type f -name "*.log" -mtime +7 -print0 | xargs -0 -I {} rsync -av {} user@backup:/backup/data/第一个写法的坑在mv "$f"双引号上,文件名带空格时不加引号会被拆成多个参数,这是常见翻车点。${f%.txt}是 shell 参数扩展,从末尾去掉.txt再拼上.md。第二个写法里find的-mtime +7表示修改时间超过 7 天,-print0用 null 分隔输出,配合xargs -0可以安全处理带空格的文件名,-I {}指定占位符,让 rsync 每次只处理一个文件。
rsync -av里-a是归档模式,保留权限和时间戳,-v显示过程。如果只是本地移动,不需要-exec mv,find ... -delete直接删,但删之前强烈建议先-exec ls -lh {} \;看一遍,别手快。
3.4 系统资源监控:top、vmstat、sar 各管一段
性能类案例看的是系统负载、CPU、内存、IO。很多新手只盯 top 的 CPU 使用率,忽略了更关键的指标。我复现这类案例时固定三件套:top 看当前状态,vmstat 看上下文切换和 swap,sar 看历史趋势。
top -bn1 | head -n 15 vmstat 1 5 sar -n DEV 1 3top -bn1表示非交互模式输出一次结果,-n 1是次数,适合脚本抓取,head -n 15截掉下面的进程列表只留顶部信息。这里重点看 load average、wa(IO wait)和僵尸进程数。vmstat 1 5是每秒采样一次、共 5 次,输出里的 r 列是运行队列,b 列是阻塞进程,si/so 是 swap 换入换出,这俩长期非零说明内存吃紧。
sar -n DEV 1 3看网卡吞吐,rxkB/s 和 txkB/s 是接收发送速率,带宽跑满时这里会有明显体现。saros 如果没有默认启用,需要安装 sysstat 包。三个命令看完一轮,CPU 忙还是 IO 忙还是网络瓶颈,基本能定位到方向。
3.5 用户与权限管理:useradd、sudo 与目录权限
用户管理案例看起来常规,但权限模型没搞清,后面故障排查会不断踩坑。新建用户这条链路我建议完整走一遍:
useradd -m -s /bin/bash zhangsan passwd zhangsan usermod -aG wheel zhangsan-m自动创建家目录,-s指定登录 shell,passwd设置密码,usermod -aG wheel把用户追加到 wheel 组,-a是 append,-G是附加组,这样用户才能用 sudo(Debian 系对应组名是 sudo,不是 wheel)。
目录权限这块,chmod 755和chown user:group是最基本的,但多人协作时用 ACL 更精准:
setfacl -m u:zhangsan:rwx /data/project getfacl /data/projectsetfacl -m给指定用户单独授权,不用改属主,getfacl查看实际生效的权限列表。ACL 在 100 例里不一定出现,但生产环境经常会用到,特别是多个团队共用一台机器的场景。权限类案例复现完最好自己造一个多用户环境测一遍,比只看命令输出记得牢。
4. 运维故障案例的排查套路:从现象到根因的四步路径
故障类案例在这份资源里占比接近四成,是含金量最高的部分。网上很多 linux 运维故障案例帖写得玄乎,本质都是同一套思路:确认现象、缩小范围、定位根因、验证修复。我复现的时候会把每个故障案例强行套进这条路径,套不进去就先停手查资料,而不是乱敲命令。下面三个是最常考也最常出问题的场景。
4.1 服务起不来的排查顺序
服务起不来是出现频率最高的故障,没有之一。很多新手的习惯是systemctl restart一遍遍地试,这属于把重启当后悔药,碰运气成分太大。我固定按状态、日志、端口、权限四步走。
systemctl status nginx journalctl -u nginx --since "10 min ago" --no-pager | tail -n 30 ss -tlnp | grep :80 ls -l /usr/share/nginx/html/第一步systemctl status nginx会直接告诉你服务是 running、dead 还是 failed,failed 时还会带一句失败原因描述。第二步进 journald 看最近 10 分钟内的日志,语法错误、bind 失败、配置文件缺失都会打在这里。第三步ss -tlnp | grep :80是应对端口被占的,如果 nginx 想监听 80 但已经被别的进程占了,日志里会出现Address already in use。第四步查权限,最常见的是目录属主不对,nginx 工作进程读不了静态文件。
这个场景里最容易忽略的一个隐蔽原因:系统时间没同步。日志时间和证书校验都会出问题,timedatectl status看一眼时间源,如果没同步就先timedatectl set-ntp true修正时间再排查其他项。别问我为什么知道,凌晨三点被时间偏差坑过的人都会记得。
4.2 内存耗尽与 OOM:先看内核日志再谈优化
内存类故障的现象往往是 SSH 都连不上,或者服务进程莫名其妙消失。遇到这种情况第一反应不是看 free,而是看内核日志有没有 OOM 记录。
free -h dmesg | grep -i oom | tail -n 20 journalctl -k --since "1 hour ago" | grep -i -E "oom|killed process"free -h看的是当前内存快照,但 OOM 发生之后内存可能已经释放,盯这个判断不了。dmesg | grep -i oom才是关键,内核在杀进程之前会在 ring buffer 里记录哪一次触发了 overcommit、哪个进程被 killed,PID 和内存占用都会列出来。journalctl -k是找 kernel 日志,适合 systemd 环境下日志已经被 journal 接管的情况。
拿到被杀的进程名之后,才能判断是进程本身内存泄漏,还是 cgroup 配额设置太小,或者是同一台机器其他进程把内存吃光连累了它。我在容器环境里遇到过好几次:进程在宿主机 free 显示正常,但容器 cgroup 限额到了被 OOM killer 干掉,这时候要查的是 cgroup 配置而不是加内存。这类案例提醒我,现象和根因往往隔着两层,别用直觉代替数据。
4.3 端口冲突与连接数异常:ss 和 lsof 的定位方法
端口类故障是两个极端:一个是端口起不来,一个是连接数撑爆。前者在第 4.1 节覆盖过,这里重点说连接数异常。先看整体状态再定位到具体连接:
ss -s ss -tan | awk 'NR>1 {print $1}' | sort | uniq -c | sort -nr lsof -i :8080 | grep ESTABLISHED | wc -lss -s输出 socket 汇总,ESTAB、SYN-SENT、TIME-WAIT 的数量一眼能看出是哪种异常。TIME-WAIT 特别多通常是短连接风暴,SYN-SENT 堆积说明对端响应不过来。第二条是统计当前所有 TCP 状态的数量分布,ss -tan里-a表示 all,-t是 TCP,-n不反解;awk 取第一列状态字段,后面的 sort、uniq、sort 管道和第 2 章的日志统计是同一个套路,换个场景就能复用。
lsof -i :8080 | grep ESTABLISHED | wc -l是数某个端口的活跃连接数。配合性能监控案例里的ulimit -n查看进程文件描述符上限,如果连接数接近上限,光调应用没用,得改LimitNOFILE或 sysctl 的net.core.somaxconn。排查网络故障最容易翻车的点就是只看现象不谈上限,连接数异常背后几乎都有配额或内核参数在卡脖子。
5. 复现100例时最容易踩的坑:五条血泪记录
这一章是全篇最想让你先看的部分。这些坑不一定写在 100 例原文里,但复现或者迁移到生产环境时几乎必踩。我按「现象 → 原因 → 解决」逐一记录,都是我实际走过的路,第五个尤其隐蔽。
5.1 变量为空导致 rm -rf 误删
现象: 在脚本里写rm -rf $DIR/$SUB清理目录,运行时拼命报错,一看,$SUB因为某个分支没有赋值,命令变成了rm -rf $DIR/,直接把整个目录树删了。运气差的话,后面再加个/*,后果不敢想。
原因: Shell 变量引用没有加防护,变量未赋值时被解释成空字符串,命令仍然继续执行。rm -rf对空路径的处理不是报错,而是指向了父目录。
解决: 所有涉及rm -rf的路径必须加空值检查,或者直接用参数扩展的默认值保护:
rm -rf "${DIR:?变量 DIR 未设置}" rm -rf "${DIR}/${SUB?}"${DIR:?}是 shell 的 parameter expansion,变量为空或未定义时直接报错退出,而不是继续执行删除。从那以后我写任何清理类脚本都会在开头先校验关键变量。
5.2 带空格的文件名让 for 循环直接翻车
现象:for f in $(find . -name "*.log")复现批量处理案例,一执行就报「No such file or directory」,仔细看,文件名明明是test 2024.log,被拆成了test和2024.log两个词。
原因:$(...)命令替换的结果按空格分词,for 循环把它当成多个独立的词处理。Linux 文件名里允许空格,这在生产环境并不少见,尤其是从 Windows 传上来的文件。
解决: 不要用命令替换接 for,用while read配合find -print0:
find . -name "*.log" -print0 | while IFS= read -r -d '' file; do echo "处理: $file" done-print0让 find 用 null 字符分隔文件名,read -d ''按 null 读取,IFS=禁止修整空白,这样带空格、换行的文件名都能安全处理。写脚本时凡是遍历文件,直接默认用这个姿势,能省掉一半的玄学报错。
5.3 set -e 与管道:脚本静默退出
现象: 脚本开头写了set -e,跑起来没有任何报错,但中间的循环后半段没执行,生成的日志也不完整。
原因:set -e是「任何命令返回非零立即退出」,而管道命令的退出码默认取最后一个命令的。比如grep 某关键词 file | wc -l,grep 没匹配到返回 1,但 wc -l 始终返回 0,所以不会退出;反过来,如果最后一个命令返回非零,前面的命令失败反而被忽略,脚本就在你意想不到的位置中断。
解决: 把脚本头部写成这样:
set -euo pipefail-u让未定义变量直接报错,-o pipefail让管道中任何一个命令失败,整个管道都返回非零,和set -e配合时不会漏掉中途失败。代价是你得把每个可能失败的步骤都处理干净,但对生产环境来说,这是必须的成本。复现脚本类案例时建议直接套这行开头,能提前暴露很多问题。
5.4 nohup 挂后台后,SSH 断开进程还是没了
现象:nohup long_task.sh > run.log 2>&1 &在终端里跑得好好的,一关 SSH 窗口,过一会儿进程就没了,日志停在某个位置不再更新。
原因:nohup只是忽略 SIGHUP 信号,但终端关闭时会话组里的进程可能还会收到 SIGHUP 以外的信号,或者进程本身是当前 shell 的子进程,shell 退出后它失去控制终端,行为变得不可控。这在「让后台运行指令不因界面退出而退出」的场景里有不少人翻车。
解决: 三个办法按可靠度排序。最简单的是nohup command &之后补一个disown,把任务从 shell 的任务表里移除,shell 退出时不再追踪。更稳的是用setsid让进程完全脱离会话。最规范的,systemd 环境直接写 service 单元文件交给 systemd 管:
setsid nohup /opt/scripts/long_task.sh > /var/log/long_task.log 2>&1 &生产环境我一般优先选 system-run 或者写 service 文件,因为还能挂依赖和自动重启。复现这类案例时顺便把三种方式都跑一遍,理解它们对会话和信号的差异,比背参数有用得多。
5.5 crontab 里的脚本环境变量不生效
现象: 脚本在终端手动执行完全正常,放进 crontab 后运行失败,日志里报 command not found 或者路径不存在。比如脚本里写mysqldump,终端能执行,cron 环境里找不到。
原因: crontab 执行脚本时环境极其精简,PATH 只有/usr/bin:/bin,不加载用户的.bash_profile和.bashrc,所以export PATH的配置都不生效,非标准路径下的命令自然找不到。
解决: 三种手段叠加使用最稳妥。第一,所有命令写全路径,/usr/local/mysql/bin/mysqldump而不是mysqldump。第二,脚本开头显式 source 环境变量文件。第三,crontab 里单独设 PATH:
# crontab -e 文件顶部 PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin SHELL=/bin/bash # 脚本内部开头 source /etc/profile source ~/.bashrc从 4.2 到 5.5,这几个坑的共同点是现象都像玄学,原因都在基础细节。排查时先看环境变量和命令全路径,会省下很多无用功。
6. 把100例变成自己的运维手册:整理与扩展的正确姿势
案例集跑完一遍之后,别急着放下。真正拉开差距的,是把别人的 100 例整理成自己的运维手册。我自己的做法是建一个笔记仓库,按「场景—命令—检查点—踩坑」四要素记录每一条案例,每条案例补上当时复现的环境(CentOS 7 还是 Ubuntu 22.04、内核版本多少),因为很多命令的差异就藏在环境里。比如/var/log/secure和/var/log/auth.log的路径差异,不记录的话下次换系统照样踩。
记录格式不复杂,但要坚持。每个故障案例写清三行:现象是什么、用什么命令缩小范围的、根因是什么。别写废话,只写命令和结论。下面是我整理nginx 起不来这类案例时的真实格式:
# 场景: nginx 起不来 systemctl status nginx journalctl -u nginx --since "10 min ago" --no-pager ss -tlnp | grep :80 # 上次根因: 80 被另一个孤儿进程占着 # 解决: fuser -k 80/tcp 之后 restart,并修复了那个进程的退出逻辑做完这一步,再把生产环境里遇到的问题反哺进手册,标注「生产遇到」「与案例差异」等标签。每周挑一个故障案例不看笔记完全复现一遍,模拟面试题里「你怎么排查」的追问,能写全排查路径,才算真掌握。
还有一个小技巧,很多人忽略:把常用的长命令写成函数,塞进.bashrc。比如把上面那条日志统计管道写成failip(),每次想查攻击来源直接敲函数名,效率翻倍。100 例不是终点,是你的起点。从那以后我每换一台新环境,第一件事就是按手册搭一遍监控和日志采集流程,强制自己重新走一遍排查路径——坚持一年下来,踩坑频率明显降了。希望这些拆解对你有帮助,动手跑一遍,比收藏十遍都强。
本文还有配套的精品资源,点击获取