Linux命令实用指南:从文件操作到网络排查的深度解析
发布时间:2026/10/19 7:42:28 锦皓数字建站

很多人用了好几年 Linux命令也敲得飞快但真到排障的时候还是会手忙脚乱。这篇文章不打算罗列命令手册而是想把日常最常用的一批 Linux 命令重新讲透它们为什么这么设计使用中真正容易踩的坑在哪怎么组合起来解决实际问题。适合刚入门的开发者建立正确认知也适合已经写了不少脚本的老手回来查漏补缺。命令这个东西单独背参数没有意义关键是要理解每条命令在链路里的位置。文件操作管的是数据怎么放文本处理管的是内容怎么筛进程管理管的是服务怎么跑权限体系管的是谁能碰网络工具管的是数据怎么通。把这五块串起来你面对一台陌生服务器时就不会慌。1. 文件与目录操作路径、通配符与链接的底层逻辑1.1 绝对路径与相对路径不只是写法差异很多教程只说绝对路径从/开始相对路径从当前目录开始但很少说清楚这个差异在真实环境里会造成什么后果。我的建议是交互式操作时相对路径很方便但凡是写进脚本、定时任务、systemd 服务里的路径一律用绝对路径或者先cd到固定目录再执行。原因很简单脚本的执行目录不是固定的。手动在终端里跑没问题但定时任务默认可能从用户的家目录或者根目录开始执行。如果你脚本里写的是rm -rf ./cache那清理的可能不是你想清理的目录。我见过某开发者为了省事在脚本里连续cd结果最后一段命令运行在了错误的目录导致文件被删错位置。这个坑踩一次就长记性了。另外一个实用细节cd -能回到上一次所在的目录原理是 shell 把上一个目录记录在环境变量$OLDPWD里。在脚本里如果想在两个目录之间来回切换可以这样cd /data/app ./build.sh cd -不过更稳的做法还是用子 shell 或者pushd、popd避免脚本中途切换目录把后续逻辑搞乱。子 shell 的写法是(cd /data/app ./build.sh)这样目录切换只影响子 shell 内部父 shell 的当前目录不变。这个细节在写部署脚本时特别实用。1.2 通配符与花括号展开通配符*、?、[]是新手最先接触的批量匹配方式。bash 会先做路径展开再把展开后的结果交给命令。比如ls *.log会把所有以.log结尾的文件名列出来没有匹配时 bash 会把原来的*.log字符串原样传给命令这时候ls会提示文件不存在。这里有个非常危险的场景如果目录里没有匹配项执行rm *.txt会报 No such file or directory这还算好的。但如果因为变量为空导致rm -rf $DIR/*被展开成rm -rf /后果就是灾难性的。所以脚本里如果变量可能为空必须加判断if [ -n $DIR ]; then rm -rf $DIR/* fi还有个很容易被忽略的技能花括号展开。它和通配符不一样不依赖文件是否存在。比如touch {a,b,c}.txt会创建三个文件for i in {1..10}; do echo $i; done可以生成序列。批量备份时可以用cp app.log{,.bak}这一条会把app.log复制成app.log.bak比打两遍路径方便得多。如果要对一批文件做相同操作花括号展开比*更可控因为它不会误匹配不该处理的文件。1.3 硬链接与软链接的取舍ln默认创建硬链接ln -s创建软链接。很多人只知道软链接像快捷方式但没搞懂硬链接的本质。硬链接是同一个 inode 的多个目录项删除任何一个路径数据都还在软链接是保存目标路径的独立文件目标被删除后软链接就变成了断链。什么时候用硬链接典型场景是日志轮转和备份。比如某些日志管理工具会把当前日志文件硬链接到另一个地方这样即使原路径被轮转删除备份路径里的数据仍然存在。但硬链接有两个限制不能跨文件系统不能对目录创建。想给目录做链接就只能用软链接。软链接最坑的一点是相对路径的写法。如果你在/data/app下面执行ln -s /data/app/config.ini /tmp/config.ini没问题但如果你用相对路径写ln -s config.ini /tmp/config.ini这个链接保存的是相对于/tmp的位置跳转到/tmp后再访问config.ini就会断裂。经验是创建软链接时尽量用绝对路径或者在目标目录下算好相对路径再写。2. 文本处理三剑客grep、sed、awk的正确组合方式2.1 grep比你想的更能过滤grep是很多人学会的第一个过滤命令但使用水平普遍停留在grep keyword file。其实配好参数能解决很多实际问题-E使用扩展正则省掉一堆反斜杠。-v反向匹配。-c只计数。-o只输出匹配到的部分而不是整行。-q静默模式不输出任何内容只返回退出码。退出码在脚本里特别好用。grep的退出码是0 表示找到匹配1 表示没有匹配2 表示文件不存在或读取失败。所以可以这样写if grep -q ERROR server.log; then echo 日志里有异常 fi如果直接写grep ERROR server.log匹配结果会刷屏在脚本里没有意义。静默模式就是要告诉 shell我只关心有没有不关心具体内容。另一个容易踩的坑是二进制文件。grep遇到二进制文件会输出Binary file xxx matches这个提示有时候会干扰管道解析。可以加-a把二进制当文本处理或者用--include*.log限制只搜索日志文件。比如统计当前代码库里 Python 文件的待办数量grep -rn --include*.py TODO . | wc -l一条命令解决人工翻文件的低效问题。2.2 sed地址定界与批量替换sed是流编辑器最常见的用法是s/old/new/g做全局替换。但真正的威力在于地址定界。比如sed -n 10,20p file.txt # 只看第10到20行 sed /^#/d config.conf # 删除注释行 sed 2,5s/^/prefix_/ file.txt # 给第2到5行加前缀批量替换是最高频的操作但有一个非常常见的误区不加-i的时候sed只是把处理结果输出到屏幕原文件纹丝不动。很多人第一次用sed s/a/b/g file看完屏幕以为自己改好了结果文件根本没变。要真正写回文件必须加-i参数。-i的语法在不同系统上还不一样。Linux 上的 GNU sed 可以直接写sed -i s/a/b/g file而 mac 自带的 BSD sed 要求写成sed -i s/a/b/g file。如果我写的脚本要跨平台使用我通常用perl -pi -e s/a/b/g file替代语法统一不容易踩系统差异的坑。sed替换里的表示被匹配到的完整内容这个技巧用于给匹配内容加装饰很顺手。比如把配置文件里所有端口号行加上注释sed -i s/^port .*/# / config.conf原来port 8080会变成# port 8080不用手动补注释符。2.3 awk列处理与状态机的思想awk是文本处理里最难学但最值得学的工具。很多人被它复杂的语法劝退其实只要抓住一点awk把每一行拆成列然后对每一列做处理。默认按空白分隔$1是第一列$NF是最后一列$0是整行NR是当前行号NF是列数。最实用的场景是配合命令输出做统计。比如提取根分区磁盘使用率df -h / | awk NR2 {print $5}NR2是因为df输出第一行是表头取第二行才是根分区信息。如果想算某列最大值awk {if($3max) max$3} END{print max} data.txtBEGIN和END分别在第一行处理之前和最后一行处理之后执行这种模式很适合写简单报表。很多人以为awk只能在文本文件上工作其实它可以配合任意命令的输出使用这才是它真正的价值。有一个细节非常容易踩坑在awk的 program 里直接使用 shell 变量会失效因为单引号里的内容不会做 shell 展开。正确做法是用-v传参threshold80 df -h / | awk -v t$threshold NR2 {gsub(%,,$5); if($50t) print $5}gsub在这里把百分号去掉0把字符串转成数字才能和阈值比较。这个写法可能有点长但实际排查磁盘告警时非常管用。3. 进程与资源问题从定位到处理的完整排查思路3.1 ps 输出的字段怎么看服务器负载高了第一个念头就是跑ps aux。这一堆列分别代表USER运行用户PID进程号%CPU和%MEMVSZ虚拟内存RSS常驻物理内存TTY关联终端STAT进程状态TIME累计 CPU 时间COMMAND是具体命令。STAT这一列是判断进程健康度的关键。R表示正在运行S表示可中断睡眠D表示不可中断睡眠通常是进程正在等待磁盘或网络 IOZ表示僵尸进程。如果看到一堆Z说明父进程没有正确回收子进程这通常需要重启父进程才能清掉。排障时最常用的是按资源排序。快速找出 CPU 占用最高的前十个进程ps aux --sort-%cpu | head -10如果要查内存就把%cpu换成%mem。我个人的习惯是看到服务器告警先跑这一条再配合top看实时变化判断是持续占用还是瞬时抖动。还有个细节pgrep和pidof可以快速找到进程号不必在ps输出里翻。比如pgrep -f nginx: worker会精确匹配完整命令行比只匹配进程名更靠谱因为进程名可能被截断。3.2 top/htop 里真正需要盯的指标top第一行的load average有三个数字分别代表 1 分钟、5 分钟、15 分钟的平均负载。很多人以为负载高就是 CPU 忙不完全是。负载统计的是处于运行状态和不可中断状态的进程数量。如果服务器是 8 核负载持续超过 8通常说明资源已经饱和或者有进程卡在 IO 上。%Cpu(s)这一行里us是用户态 CPUsy是系统态 CPUid是空闲wa是 IO 等待。最有迷惑性的是wa。当wa很高而id很低时说明 CPU 在等磁盘这时候再怎么优化代码都是白费力气应该去查存储延迟、磁盘队列和网络文件系统的情况。内存部分很多人一看free -h里面used很高就紧张。其实buff/cache是内核用空闲内存做的缓存是需要时可以被回收的并不是泄漏。真正要看的是available这一列它表示在不交换的情况下还能分配给新进程的内存这才是实际可用量的估算值。top里还可以直接按P键按 CPU 排序按M键按内存排序这在交互式排查时比反复敲命令快得多。htop是top的增强版支持彩色显示和鼠标操作个人用起来体验更好但多数服务器默认没有装需要手动安装。3.3 处理僵死进程与退出码服务挂了的处理顺序很多人一上来就kill -9这不推荐。kill默认发送TERM信号相当于礼貌地请进程退出进程可以捕获TERM做清理工作。如果进程已经卡死TERM没有效果再考虑KILL。KILL信号不能被捕获由内核强制结束但它不保证进程的清理逻辑被执行所以是最后手段。kill -9都杀不掉的时候先看进程状态是不是D。D状态表示进程处于不可中断的内核态等待通常是磁盘 IO 或网络存储卡住信号要等 IO 返回后才能处理。这种时候你只能排查底层存储单纯反复kill没有意义。另外不要忘了timeout命令。执行一条可能卡住的命令时用timeout 30 ./some_task.sh可以让它在 30 秒后自动超时退出。这在写脚本时非常重要能避免整个任务因为一条命令挂死而无法结束。后台运行也需要区分。命令加只是放到后台终端关闭时它可能收到挂断信号退出。nohup command 才能让命令在退出终端后继续运行。但这两个都不是真正的守护化如果需要长期跑服务应该用 systemd 管理它负责进程拉起、重启、日志收集比裸nohup可靠得多。4. 权限不只是chmod用户、组与umask的协作机制4.1 把权限位当成二进制来读权限位其实就三组属主、属组、其他人每组三位rwx。数字表示法里r4, w2, x1所以744就是属主可读写执行其他人只读。目录的权限和文件的权限有本质区别。目录的r权限只能让你列出文件名w权限能让你在目录里新建或删除文件x权限才是进入目录的通行证。很多人遇到Permission denied时只想到chmod 644或755其实如果是要进入目录访问里面的文件必须有x权限。推荐的做法是目录统一用755普通文件用644只有明确需要执行的脚本才用755。有个经典场景最能说明目录x权限的作用如果一个目录只有r--权限你能ls看到文件名但cd进入时会被拒绝访问里面任何一个文件也都提示无权限。这个表现很容易让人误以为是文件权限的问题实际是目录缺x。4.2 为什么 777 是坏味道网上很多教程为了省事直接chmod -R 777这种做法的危害只有在出问题时才凸显。777意味着任何人都能读写执行一旦某个目录被写入恶意脚本服务权限边界就完全消失了。最小权限原则不是空话。如果只是需要让服务能写某个目录更合理的做法是确定服务运行的用户和组然后把目录属主设为该账号或者把目录属组设为服务账号所在组再给属组加写权限。例如chown app_user:app_group /var/www/uploads chmod 750 /var/www/uploads这样只有服务账号能写其他人连进入目录都不行。权限往小里给后面排查问题时能少很多安全顾虑。还有一个容易被忽略的点粘滞位。/tmp目录的权限通常显示为1777那个前置1就是粘滞位。它表示在这个共享目录下只有文件属主、目录属主或管理员能删除自己的文件。如果没有粘滞位任何能进入/tmp的人都能删掉别人的临时文件。共享目录加粘滞位是常见做法chmod t /shared/tmp4.3 umask 决定新文件的默认权限umask是一条很少被注意、但非常影响协作的命令。它是权限屏蔽字不是权限本身。通常发行版默认umask 022意思是新创建的文件需要去掉属组和其他人的写权限。所以新建普通文件是644新目录是755。为什么文件和目录初始权限不一样因为文件创建时的默认权限是666目录是777再减去umask。文件从没有执行权限的666减去022得到644目录从777减去022得到755。这个机制保证了普通新建文件默认不是可执行的。如果团队成员经常发现上传的文件别人无法读取或修改先查umask。在/etc/profile或~/.bashrc里可以设置。比如设置umask 002那么同组的人可以写新文件适合协作目录。但要权衡安全性公共环境不要轻易改成000那会让所有人都能改你的文件。4.4 chown与属主属组导致的启动失败线上服务启不来第一件事看日志第二件事看文件属主。很多手动部署场景里用管理员账号拷贝文件到服务目录结果服务以专用账号运行读取不到属主是自己的文件直接报权限错误。解决方式很简单ls -l看属主然后chown -R app_user:app_group /data/service但chown -R也是一个危险操作它会递归修改大规模目录。如果路径写错可能导致系统文件属主混乱。执行之前先用ls -ld确认目标路径再操作。改完一遍之后抽查几个文件确认属主符合预期别急着收工。5. 网络排查命令不是背出来的是查出来的5.1 先确认连通性ping 的局限ping是大家最爱用的网络测试命令但它的局限性很多人不清楚。ping走的是 ICMP 协议很多云主机默认禁止 ICMP 响应所以ping不通并不代表服务不可用反过来ping通了也不代表应用层正常。比如数据库服务没启动但主机ping照常通。排查问题时我一般分两层看主机层面用ping确认基本连通端口层面用nc或telnet确认端口可达。一条命令直接测端口nc -zv target_host 3306返回Connected说明端口可达。这比ping靠谱得多因为它直接测试了你真正关心的那条链路。5.2 端口与连接ss 比 netstat 更值得学netstat是老牌命令但很多新系统默认已经不自带了推荐直接用ss。ss是 socket statistics 的缩写速度快信息全。最常用的一组参数是ss -tunlp-t显示 TCP-u显示 UDP-n不做域名解析-l只看监听端口-p显示对应进程。这一条命令就能看出哪个端口被哪个进程占用。如果想看当前所有已建立的连接ss -tn state established排查连接数异常时很有用。TIME_WAIT状态多通常不是问题它是 TCP 主动关闭连接的正常过渡状态。如果看到大量SYN-SENT或SYN-RECV那才是需要警惕的说明连接根本建立不起来可能是对端拒绝或网络被拦截。5.3 curl一条命令完成接口调试curl是排查应用层问题的最强命令没有之一。推荐几个最常用的参数组合curl -i显示响应头。curl -v打印完整请求和响应过程包括 TLS 握手。curl -L跟随重定向。curl -X POST -H Content-Type: application/json -d {name:test} http://host/api发送带 JSON 的 POST 请求。curl --max-time 5限制超时时间防止命令卡住。实际排查时先用-i看状态码。如果是502或504基本可以判断问题在反向代理后面的服务而不是curl本身。如果是200但内容不对可能是缓存或路由问题可以在 URL 后面加个无意义参数绕过缓存。curl -v输出里重点看这几处Connected to表示 TCP 连接建立成功SSL connection using TLS表示 TLS 握手正常GET /path HTTP/1.1是实际请求行。如果 SSL 报错而业务用的是 HTTP那就说明访问协议选错了。5.4 DNS层面getent与解析顺序很多网络问题出在 DNS 解析上。ping域名通但curl域名不通这类现象多半和解析结果或应用自身的解析方式有关。系统解析主要看/etc/nsswitch.conf里hosts的配置顺序一般默认是files dns也就是先查/etc/hosts再查 DNS 服务器。getent hosts 域名可以显示系统最终采用的解析结果。修改/etc/hosts后大多数应用即时生效但如果应用用了自己的 DNS 缓存或客户端可能要重启进程才能读到新记录。排查时也可以用dig short 域名直接查 DNS 记录但要记住dig跳过/etc/hosts它查的是 DNS 服务器和系统实际解析不完全一致。所以判断为什么这个域名解析到不同 IP时要以getent hosts的输出为准。最后说一点我自己的感受。Linux 命令学到最后记忆负担其实不大真正值钱的是你理解每个命令输出里的关键字段并把它们串成排查思路。比如看到负载高想到ps看到可用内存低想到buff/cache看到权限拒绝想到属主、umask、目录x权限看到端口不通想到ss和curl。这套东西不是一天练成的但只要每次遇到问题都把链路上每个命令跑一遍慢慢就会形成肌肉记忆。希望这篇能帮你把常用命令用得更明白。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。