Linux命令场景实战:管道重定向与日志排查高频技巧 第一次接手一台没有任何图形界面的 Linux 服务器时很多人脑子是懵的黑底白字的终端连个文件夹都打不开更别提装环境、查日志、看报错了。网上搜linux常用命令能搜出几百个命令清单但真到了现场你还是不知道用哪个。我的看法是Linux 命令不需要背需要按工作场景去理解。这篇文章不打算给你列一份字典式的命令大全而是按照我实际运维和开发中最高频的场景把命令怎么组合、为什么这样用、哪些地方容易翻车讲清楚。适合刚开始做运维、从 Windows 切到 Linux 的后端开发以及准备 Linux 相关面试的人。1. 命令不是背出来的先理解管道、重定向、一切皆文件1.1 管道把多个命令拼成一条流水线Linux 命令最容易被新手忽略的地方就是它天生就是为组合设计的。单个命令能力有限但通过管道符|把前一个命令的输出接到后一个命令的输入等于把好几个小工具串成一条流水线。举个例子你想知道今天某个接口报错了多少次。最原始的做法是打开日志文件人眼数但正确做法是grep /api/login app.log | grep ERROR | wc -l这条命令干了三件事先筛出含/api/login的行再从中筛出含ERROR的行最后数行数。wc -l的-l是数行数如果只要数字它是终端里最常用的计数器。管道真正厉害的地方在于它能把任何输出是文本的命令串在一起。比如ps -ef | grep java是找进程的经典组合ls -lh | sort -k5 -hr可以看当前目录谁最占空间。你先不用背几十个参数记住任何命令的输出都可以塞给另一个命令处理这个思路后面所有命令都会活起来。这里有个很实在的坑管道整体的退出码只取决于最后一段命令。比如grep NonExist app.log | wc -l即使前面 grep 一个都没匹配到wc -l照样输出 0而且整条命令的退出码是 0成功。在写脚本时这会导致你判断日志里有没有报错时误判。解决方法是给 bash 加上set -o pipefail让管道中任何一段失败都反映到最终退出码上。这个细节我在脚本里吃过好几次亏。1.2 重定向别再把输出丢掉或覆盖管道是把输出递给另一个命令重定向则是把输出写到文件里。三个最常用的符号覆盖写入追加写入2只重定向错误输出最经典的后台部署场景nohup java -jar app.jar app.log 21 这条命令里21很多人不理解其实意思是把标准错误文件描述符 2重定向到标准输出文件描述符 1去的地方也就是让报错信息也进日志文件。顺序很关键 app.log 21是先让 stdout 进文件再让 stderr 跟进这个文件如果写成21 app.logstderr 还是会打到终端日后再想排查就什么都看不到。还有一个实用经验清空一个大日志文件不要rm然后重新创建。如果一个进程还握着这个文件比如 Java 服务正常在写删掉文件后磁盘空间并不会立刻释放因为文件句柄还开着。正确做法是直接 app.log用重定向把文件截断成 0 字节日志进程继续写也没问题。1.3 一切皆文件对理解命令的意义Linux 有个底层哲学叫一切皆文件。磁盘、终端、网络连接在系统层面都被抽象成文件这解释了为什么很多命令看起来那么统一。比如/dev/null它是个黑洞文件你把不需要的输出扔进去就行command /dev/null 21再比如查看系统信息你其实是在读文件cat /proc/cpuinfo cat /proc/meminfo理解了一切皆文件你就不会觉得cat、less、grep这些命令有什么区别了——它们本质上都是文件的读取工具只是用法不同。这也解释了为什么很多命令会以文件路径为参数而不是像 Windows 那样主打开图形界面。想快速生成一个测试文件时就会用到/dev/zerodd if/dev/zero of/tmp/test.img bs1M count100这条命令会生成一个 100MB 的全零文件测试磁盘速度或造临时文件时很常用。2. 文件与目录权限、链接、查找中容易翻车的几个细节2.1 权限位并不复杂一次看懂 rwx 和特殊位ls -l输出的第一列像一串天书比如-rw-r--r--拆开看其实很简单第 1 位文件类型-是普通文件d是目录l是链接第 2-4 位属主owner权限第 5-7 位属组group权限第 8-10 位其他人other权限每三位就是rwx分别对应读、写、执行。没有的权限用-占位。数字表示法里r4、w2、x1所以chmod 755 script.sh # 属主可读可写可执行组和其他人只读只执行 chmod 644 app.conf # 属主可读可写其他人只读新手最容易搞混的一点目录的执行权限意味着能否进入该目录。有时候用户明明在group里但操作文件还提示没权限多半是目录缺了x权限。/tmp目录权限1777的1是粘滞位sticky bit表示目录里的文件只有属主能删。这个位在面试里经常被问到因为它是很多人第一次见到的特殊权限。2.2 软链接 vs 硬链接面试和实际操作都高频链接这个问题面试爱考、实操里也容易踩坑。软链接符号链接相当于 Windows 的快捷方式命令是ln -s /opt/app /opt/app_link软链接可以跨文件系统但如果原目标被删掉软链接就会变成悬空链接ls -l能看到红底白字访问就报 No such file or directory。硬链接是 Linux 特有概念ln /opt/app/data.txt /opt/app/data_hard.txt硬链接和原文件共享同一个 inode相当于同一个文件起了第二个名字。删除一个不影响另一个因为只要 inode 的引用计数不为 0数据就不会被回收。但硬链接不能跨文件系统也不能对目录做硬链接。这里有个必须记住的坑删除软链接要用unlink /opt/app_link或者rm /opt/app_link注意千万别加末尾斜杠。如果敲成rm -rf /opt/app_link/rm 会顺着软链接进入目标目录把/opt/app里面的内容全部删掉。我见过不止一次因为这种小事导致整个应用目录被清空的事故。2.3 查找与磁盘占用的实用组合很多同学分不清find和grep -r。一句话find按文件名找grep按文件内容找。服务端磁盘告警时下面的排查序列基本是标准动作df -h du -sh /* 2/dev/null | sort -hr | head -20 du -sh /var/* 2/dev/null | sort -hr | head -20df -h看文件系统整体使用率du -sh用人话显示目录大小。sort -hr按人类可读的数字单位K/M/G降序排序直接定位最占空间的大目录。隐藏文件在du -sh *中会漏掉排查时可以加上.[!.]*du -sh * .[!.]* 2/dev/null | sort -hr | head找超大文件用 find并且注意用-xdev别让 find 跑到/proc、/sys这类虚拟文件系统里find / -xdev -type f -size 1G 2/dev/null还有个容易被忽略的检查点df -i看 inode。小文件特别多的目录比如邮件队列、临时文件目录就算磁盘空间有剩余inode 耗尽后系统照样无法创建新文件报No space left on device却看着磁盘很空。这种问题我用find / -xdev -type f | wc -l统计过文件数量发现某个临时目录里有上百万个小文件。3. 日志排查三件套grep、sed、awk 的实战打法3.1 grep不只会搜还要会搜对grep是日志排查的头号工具但多数人只会grep 关键字 file这一种用法。真正干活时下面几个参数非常重要参数作用示例-i忽略大小写grep -i error app.log-E使用扩展正则grep -E ERROR|Exception app.log-v取反过滤grep -v 心跳 app.log-c只统计行数grep -c ERROR app.log-n显示行号出问题后能快速定位位置-A2/-B2显示匹配行的后 2 行 / 前 2 行看异常栈非常有必要-r递归目录grep -r password /etc/排查线上问题时我几乎必带上下文参数grep -n -A5 -B5 NullPointerException app.log只看异常堆栈本身而没有上下文根本不知道是哪条请求触发的。另外一个很实用的组合是grep -E配合排除干扰项grep -E ERROR|Exception app.log | grep -v NoAuthException注意grep -r在扫一些配置目录时会把二进制文件也扫一遍然后莫名输出Binary file matches。如果不想看二进制文件加-I参数跳过即可。3.2 sed编辑文件的三种常用姿势sed是一个流编辑器适合对文件批量操作。我最常用的三种姿势第一种打印指定行sed -n 100,200p app.log第二种全局替换sed -i s/127.0.0.1/10.0.0.8/g app.conf第三种删除匹配行比如去掉配置文件中的注释sed -i /^#/d app.conf还有一个高级但极其实用的时间窗提取。日志是按时间顺序写的可以直接用 sed 取某段时间内的所有记录然后丢给 grep 继续分析sed -n /2025-06-01 14:00:00/,/2025-06-01 15:00:00/p app.log | grep ERROR这里有一个非常经典的跨平台坑Linux 上sed -i s/old/new/g file没问题但 macOS 自带的 BSD sed 要求-i后面必须有扩展名否则直接报错。在 macOS 上要写成sed -i s/old/new/g file。如果你在 Mac 上写好的脚本拿到 Linux 服务器执行很容易在这一行翻车。另外从 Windows 上传上来的文本文件经常带\r回车符导致grep匹配最后一列总是对不上。解决办法sed -i s/\r$// file.txt这个坑在做日志分析时非常常见文件的每一行末尾都藏着不可见字符不处理掉的排查过程极其痛苦。3.3 awk日志分析和统计的第一帮手awk是文本处理三件套里最能打的一个它真正擅长的是按列处理。默认按空白字符切分整行$1是第一列$NF是最后一列。比如统计访问日志里哪个 IP 请求最多awk {ip[$1]} END {for (k in ip) print ip[k], k} access.log | sort -rn | head -20含义是以第一列为 key 建一个计数器数组每出现一次就加一全部处理完之后循环打印。sort -rn按数字降序排序head -20取前 20 名。用-F指定分隔符也很常见比如/etc/passwd是按冒号分的awk -F: {print $1, $3} /etc/passwd还可以做条件统计。假设访问日志第九列是状态码想统计 500 错误有多少次awk $9 500 {count} END {print count} access.log如果是 gzip 压缩的日志文件记得用zcat先解压再管道给 awkzcat app.log.gz | awk {print $1} | sort | uniq -c | sort -rn | head有一点必须提醒awk的数组是关联数组统计大量数据时会占用不少内存。我遇到过几个 GB 的大日志文件直接awk统计结果卡死后来是用split把日志切小再并行统计。所以大文件分析时先评估服务器内存再动手。3.4 一个完整的日志分析案例把三个工具串起来看一个典型的排查场景是这样的早上收到告警某接口从凌晨开始大量返回 500。先统计受影响的 IP 和数量grep 2025-06-01 app.log | grep 500 | awk {print $1} | sort | uniq -c | sort -rn | head然后取一段时间窗口看具体错误堆栈sed -n /2025-06-01 00:00:00/,/2025-06-01 00:05:00/p app.log | grep -A20 500最后找一下这个时间段里响应最慢的请求awk {print $NF, $0} access.log | sort -rn | head -10这套组合拳基本能解决绝大多数日志分析问题。关键是不要单独记命令而是记住先 grep 缩小范围再 sed 取上下文再用 awk 做统计这个流程。4. 进程、端口和资源服务器出问题时的标准排查路线4.1 找进程、杀进程ps 和 kill 的配合排查进程是运维日常。最经典的两条命令ps -ef ps aux两者展示的信息基本一致字段排列有差异。实际中配合 grep 找人ps -ef | grep java | grep -v grep这里的grep -v grep是为了去掉那条 grep 命令自身。其实更优雅的做法是用pgreppgrep -af java-a显示完整命令行-f匹配完整命令行参数比ps | grep干净很多。杀进程时默认的kill发送的是 TERM 信号15请求进程优雅退出给它时间清理资源。kill -9是 SIGKILL强制杀死进程没有机会做任何清理。我的习惯是先kill pid等两三秒看进程还在不在如果还活着再kill -9。一上来就kill -9可能会让数据库、消息队列这类进程留下未落盘的脏状态。遇到僵尸进程STAT 显示 Z时直接kill -9也解决不了问题因为僵尸进程是子进程结束后还没被父进程回收。要看它的父进程ps -ef | awk $8Z {print $2, $3, $8}第二列是 PID第三列是 PPID。正确的解决思路是让父进程处理回收通常重启或杀掉父进程即可。这个机制理解了以后排查僵尸进程不会瞎折腾。4.2 端口查询从 netstat 到 ss端口被占用是部署服务时最常见的报错。经典命令netstat -tlnp ss -tlnpnetstat在不少新系统里已不再默认安装ss是它的替代品输出更快信息类似。参数含义-t只看 TCP、-l只看监听状态、-n用端口号而不是服务名、-p显示进程信息需要 root 权限。要查某个端口到底被谁占着最直接的是ss -tlnp | grep 8080 lsof -i:8080lsof -i:8080的输出里能看到 PID 和进程名确认是自己服务的旧实例后就kill掉再重新启动。如果是个不认识的服务就不能贸然杀先查启动命令ps -p PID -f需要补充一个实际经验有些精简容器镜像里既没有ss也没有netstat更别提lsof。此时可以看/proc/net/tcp虽然不易读或者干脆进入容器执行apt install iproute2装一个。在容器环境排查端口问题时这个准备动作能省很多时间。4.3 系统资源与日志top、free、journalctl服务器异常时先看整体资源是避免瞎忙的第一步。top进入交互界面后几个键要记住P按 CPU 排序M按内存排序1展开多核 CPU 状况u后输入用户名只看某用户的进程。注意top里一个进程 CPU 如果有 150%说明它跑满了 1.5 个核心这是多核机器的正常表现别当成 bug。内存用free -h看比较直观。关键看available一列它是真正可用的内存估算值。Linux 会尽量把空闲内存用作 buff/cache文件缓存所以used高不代表内存不够available才会告诉你真实水位。很多新手看到 used 90% 就慌着加内存其实缓存是可以随时释放的。系统服务出了问题现在基本都是 systemd 的地盘。常用命令systemctl status nginx systemctl restart nginx journalctl -u nginx --since 10 min ago journalctl -u app -fjournalctl里-u按服务名过滤-f跟踪最新日志--since和时间窗口配合用比直接去翻/var/log/messages高效得多。老掉牙的service命令在兼容老系统时才用新环境都走 systemctl。我把排查顺序总结成一个习惯先free -h和df -h排除内存和磁盘再top看 CPU 和负载然后journalctl或直接看应用日志最后才是ss和ps查端口与进程。按这个顺序走大多数问题五分钟内能定位到方向。5. 终端里的高频配套工具箱vim、git、docker、redis5.1 vim 的底线记住这些就能在服务器上改文件很多刚接触服务器的人一打开 vim 就不知道怎么退出直接卡住。其实 vim 的入门门槛很低你只需要先记住一套最小操作集操作按键进入编辑模式i返回普通模式Esc保存并退出:wq不保存退出:q!删除一行dd复制一行yy粘贴p撤销u查找/关键字回车n跳下一个跳转文件头/尾gg/G跳到指定行:行号这些记住以后你就能在服务器上改配置文件了。再进阶一点CtrlV进入可视块模式用方向键选中多行后按I再输入内容再按Esc就能给连续多行批量插入同样的前缀。批量处理配置文件场景里这个技巧比手动一行行改快得多。我的建议是在服务器上不做大规模编辑。想看大日志就用less想批量改文件就用sedvim 只用来改配置。真打开一个 1GB 的日志到 vim 里整个编辑界面都会卡顿还容易误操作。5.2 git在 Linux 终端里跑得最多的非系统命令git 虽然不是 Linux 系统命令但凡是做开发终端里敲得最勤快的往往就是它。日常工作我的肌肉记忆基本是这几条git status # 看当前改了什么 git add . git commit -m feat: xxx git push git pull --rebase git log --oneline --graph -10回滚操作是很多人容易慌的地方。如果只是本地想撤销最后一次提交可以用git reset --hard HEAD~1但要小心reset --hard会丢掉提交记录和工作区改动已经 push 到远程的提交千万别这么干应该用git revert生成一个反向提交。判断能不能 reset只需要一条这个提交有没有被其他人拉到过。排查问题时会用到git diff --stat # 改了哪些文件 git stash list # 临时保存的改动 git blame file # 某一行是谁改的掌握了这几个场景git 在日常开发中就不会卡脖子了。5.3 容器与缓存docker 和 redis 的高频命令现在服务器上跑的应用很大一部分是容器化的。docker 的常用命令数量其实很少记住一套就够docker ps -a # 看所有容器包括已退出 docker logs -f --tail 100 container # 实时看容器日志 docker exec -it container bash # 进入容器内部 docker stop container docker rm container容器内应用日志通常打到 stdout所以docker logs是查问题的第一入口。磁盘老变满时docker system df可以看容器、镜像、构建缓存各占多少空间用docker system prune清理悬空镜像和构建缓存动作很大清理前先确认。redis 在服务器上也很常见一套基础命令redis-cli -h 127.0.0.1 -p 6379 -a password 127.0.0.1:6379 ping 127.0.0.1:6379 info memory这里有一个绝对不要犯的错误生产环境不要用keys *查 key。Redis 是单线程模型KEYS *会全量遍历数据量一大线上请求会瞬间被打断。想看 key 列表应该用SCANredis-cli --scan --pattern user:* | head -50SCAN是分批遍历每次取少量 key 返回对线上影响小得多。这个区别是很多初级运维和开发都不知道的坑。6. 从 Windows 过来的人命令对照与习惯调整6.1 常用命令的 Windows 对应项从 Windows 切过来最容易痛苦的是我知道在 Windows 里怎么做但 Linux 里命令是啥。一张常用对照表可以帮助快速建立映射WindowsLinux说明dirls -l列出文件cdcd切换目录用法基本一致copycp复制movemv移动或重命名delrm删除Linux 没有回收站typecat/less查看文本文件notepadvim/nano编辑文件findstrgrep在文件中搜索文本ipconfigip addr查看 IP 地址tasklistps aux查看进程taskkillkill结束进程clsclear/CtrlL清屏treefind . -type d显示目录树对照表的目的是帮你快速建立动作映射而不是让你继续在 Linux 里敲dir。因为有些发行版确实给dir配置了别名但脚本里一旦用了 Windows 命令换台服务器立刻失效。6.2 容易带过去的 Windows 习惯建议改掉从 Windows 过来的人通常有几个习惯性动作需要主动纠正。第一个是路径分隔符。Windows 用反斜杠\Linux 用正斜杠/。最初写命令时经常混着用特别是在 shell 脚本里这个错误会导致路径解析失败。第二个是文件名大小写。Windows 的文件系统默认不区分大小写Linux 区分。你在本地建了一个Config.javacommit 到 Linux 服务器上检查时发现config.java不存在这就是大小写惹的祸。第三个是删除文件不心疼。Windows 删除还有回收站Linux 的rm一旦执行文件就没了。我的习惯是不确定要不要删的文件先mv file /tmp/移到临时目录确认一周没问题后再清。第四个是用老命令管理服务。很多 Windows 管理员习惯用ipconfig、service network restart这些Linux 新系统要用ip、systemctl。尤其ifconfig在很多发行版上已经不默认安装了直接用ip addr就好。第五个是喜欢随手chmod 777解决权限问题。这个动作在 Windows 上可能是给所有人完全控制但 Linux 里它意味着任何用户都能读写执行这个文件安全隐患极大。正确的做法是只给需要的用户和组分配最小权限。我在实际使用中发现从 Windows 转 Linux 的人真正痛苦的并不是命令本身而是环境变量、权限模型、文件系统组织方式这些底层思维。命令只是外壳理解系统设计逻辑才是关键。每次接手一台陌生服务器我喜欢先敲一遍history看看之前的人是怎么操作的从历史命令里能快速摸清这台机器的用途和习惯这比翻文档有用多了。再把自己的高频长命令做成 alias比如alias llls -l --colorauto能少敲不少字。Linux 命令的积累本质是场景驱动的用一次、踩一次坑比你背十遍清单都记得牢。