干这行越久越觉得后端开发其实有一半时间不是在写代码而是在跟命令行打交道。不管是查日志定位线上问题、看服务进程还在不在、端口被谁占了、还是往服务器部署新版本绕来绕去都是那几十条 Linux 命令。很多刚入行的同事喜欢装个图形面板遇到问题先点半天界面但真正到排查故障的时候还是命令行最高效、最直接。这篇东西就是给后端开发同学的一份实战梳理把日常用得最频繁的那些 Linux 命令按场景拆开讲包括每个命令为什么这么用、有哪些容易踩的坑、以及我自己的操作习惯希望能帮你少走点弯路。我默认你手头的环境是 CentOS 7/8 或者 Ubuntu 20.04 这类主流发行版大部分命令通用的个别包管理操作我会单独说明。内容不追求大而全而是围绕后端开发真实工作流来组织适合刚转后端的新人也适合写了一段时间脚本但习惯靠复制粘贴的初级开发。看完你至少能独立完成查日志、看进程、查端口、测网络、写简单脚本这几件高频事情。1. 后端开发为什么离不开Linux命令先理清日常场景后端的代码最终跑在 Linux 服务器上这基本是行业共识。哪怕你本地用 Windows 或者 macOS 开发上了测试环境、预发环境、生产环境面对的几乎都是 Linux。既然服务跑在 Linux 上那你排查问题、运维部署、性能调优就绕不开命令行。明确这一点很重要因为很多新人把 Linux 命令当成“运维才需要学的东西”结果服务一挂自己连日志都不会看只能干等运维很被动。后端日常使用 Linux 命令的场景归纳起来就四类。第一类是看日志服务报错了、请求变慢了、数据不对了第一时间想到的肯定是翻日志。第二类是查进程和资源服务是不是还活着CPU 是不是被打满了内存够不够端口有没有正常监听。第三类是网络排查接口调不通、响应超时到底是 DNS 问题、防火墙问题还是服务本身问题。第四类是脚本化操作批量处理文件、定时跑任务、备份数据、快速部署这些都会用到 Shell 命令的组合。这四类场景对应的命令其实非常固定翻来覆去就是那么几十个。关键在于你知道在什么情况下用哪个命令以及怎么组合它们来快速定位问题。比如服务 502 了你要先看 nginx 日志还是看应用日志端口不通是先 ping 还是先 telnet这些判断比单纯背命令重要得多。另外还有一个容易被忽视的点命令输出的解读能力。同样跑一条top别人看到的是 CPU 百分比资深开发看到的是负载均衡、上下文切换和 CPU 队列的联动关系。所以后面讲每个命令的时候我不光会说参数也会说怎么看输出结果这才是真正值钱的东西。2. 文件与日志操作后端排查问题的第一战场2.1 日志查看三件套tail、grep、awk后端排查问题90% 的操作都是围着日志转。日志文件的处理命令优先级最高的就是tail、grep和awk。tail是看日志的起点。tail -f app.log可以实时跟踪日志文件的输出新写入的内容会立刻打印到屏幕上调试接口或者观察服务启动过程非常方便。我自己习惯再加个-n参数比如tail -100f app.log这样打开文件的同时会先把最后 100 行打印出来避免两眼一抹黑。这个命令还有一个衍生用法tail -n 50 app.log表示只看最后 50 行适合快速瞄一眼最新状态不加-f就不会一直挂在那。grep用来过滤日志内容按关键字搜索报错信息。最常用的组合是grep ERROR app.log把所有错误行拎出来。这里的坑在于日志里同一个错误可能刷出几千行你得加参数去控制上下文比如grep -A 5 NullPointerException显示匹配行后面的 5 行grep -B 5显示前面的 5 行grep -C 5显示前后各 5 行。查 Java 异常栈基本离不开这个不然你只能看到一行异常摘要根本不知道异常发生在哪段调用链上。grep还可以配合正则表达式做更精准的匹配。比如你想查某个时间段内的日志很多日志框架默认会输出2025-01-12 10:15:22这样的时间你可以用grep ^2025-01-12 10:15 app.log把这一分钟内所有请求筛出来。这个技巧在追查线上偶发问题时特别管用不用把整天的日志都拉下来看。awk是文本处理的瑞士军刀。它按列切割文本适合提取日志里的结构化字段。比如日志行格式是时间 - 用户ID - 接口名 - 耗时你想统计每个接口的平均耗时用awk {print $3}先把接口名字段切出来再传给sort | uniq -c统计次数或者进一步算平均值。很多新人觉得 awk 语法奇怪不想学其实你只需要掌握$0整行、$1第一列、$NF最后一列这几个变量再加上print和简单条件判断就能覆盖大部分场景。2.2 文件查找与内容替换find、sed、vim日志文件经常分布在多个目录或者按天切片成几十个文件这时候就要用find来定位。find /data/logs -name *.log -mtime -3表示在/data/logs目录下找所有扩展名为.log且三天内修改过的文件。-mtime参数在处理历史归档日志时非常实用避免手动数文件。你也可以用find /data/logs -name *.log -size 100M找出超大日志文件磁盘告警时排查看是谁把磁盘写满了。sed主要用于文本替换和流式编辑。后端开发经常要改配置文件里的 IP、端口或数据库连接串比如sed -i s/old_ip/new_ip/g application.yml可以原地替换所有匹配内容。注意-i参数是直接修改文件操作前最好先cp备份一份或者把-i换成-i.bak让 sed 自动生成备份文件。我做批量替换之前一定会先不加-i执行一遍看替换结果是否符合预期确认无误后才加-i真正落盘。这是保命的习惯。vim在服务器上编辑文件还是绕不过去。很多前端开发看到 vim 就想跑但后端至少要会三件事打开文件、按i进入编辑模式、按Esc后输入:wq保存退出。再进阶一点学会/关键字搜索模式和:set nu显示行号。日志报错会提示行号拿到后直接vim 文件名 行号定位到具体位置比在几万行的文件里用眼睛找高效得多。还可以用G跳到文件末尾gg跳到文件开头。够了真的够用别去深究那么多花哨操作。2.3 日志操作的一个完整排查示例举个例子。某天线上接口报 500应用日志里有大量Connection timed out。我拿着日志先做这几步先用tail -200f app.log确认错误是否还在持续刷然后grep -n Connection timed out app.log | tail -50把最近 50 条错误行号取出来再用sed -n 1200,1250p app.log查看这个区间的完整上下文看看报错前的调用方是谁。如果错误集中在某一个上游服务我就用awk {print $4} app.log | sort | uniq -c | sort -rn统计各上游 IP 的报错次数找出调用量最大的来源然后和网络同事一起排查链路。整个过程没有打开任何图形工具全部是这几个命令的组合。3. 进程、端口与系统状态服务是否健康一看便知3.1 ps 与 top看进程和资源占用后端服务通常是一个常驻进程我们要确认它是否还活着、资源占用是否正常第一反应就是ps。我最常用的写法是ps -ef | grep java找出所有 Java 相关进程。ps -ef显示全部进程的完整信息包括 PID、父进程 PID、CPU 和内存占用、启动命令等。grep过滤之后有个小坑会同时匹配到你刚才执行的那条grep命令本身所以输出里总有一个grep --colorauto java的残留行看起来像个多余的进程。解决办法是用grep -v grep把它过滤掉或者直接写成ps -ef | grep [j]ava利用字符类匹配技巧避免匹配到自身。这两种都是老手的常用套路。ps只看瞬间状态要看动态变化就得用top。top每隔几秒刷新一次系统整体状态负载均衡、CPU 使用率、内存占用、各进程的资源排行。按下P按 CPU 排序按下M按内存排序这两个快捷键一定要记住。服务 CPU 飙高时先top看一眼哪个进程吃满了 CPU然后记下 PID再top -p PID单独观察这个进程内部的状态可以进一步按线程维度排查是不是某条线程死循环或触发 GC 抖动。top输出的负载load average三个数值分别代表 1 分钟、5 分钟、15 分钟的平均负载。这里是新手最常见的误判点负载高不等于 CPU 满它计算的是处于可运行状态和不可中断状态的进程数。如果 1 分钟负载明显高于 15 分钟负载说明系统近期压力在上升如果负载很高但 CPU 使用率很低有可能是有大量进程在等待 I/O比如磁盘读写瓶颈这时候再去排查磁盘才是正确的方向。3.2 netstat 和 ss谁占用了 8080 端口服务端口被占用导致启动失败这几乎是每个后端都遇到过的经典问题。查端口占用netstat -tlnp | grep 8080是最广为人知的组合。-t只看 TCP-l只看监听状态-n不解析主机名直接显示 IP-p显示对应的进程 PID 和名称。输出里会明确告诉你 8080 端口被哪个 PID 占用拿到 PID 后ps -ef | grep PID或者直接用kill -9 PID处理。不过现在很多新系统更推荐ss命令因为它比 netstat 快很多尤其是连接数上万时差距明显。ss -tlnp | grep 8080的效果和 netstat 一致输出格式也类似。如果你发现端口处于TIME_WAIT状态不用太紧张这是 TCP 连接正常关闭后的短暂状态但如果你发现TIME_WAIT数量涨到几千甚至几万多半是服务端的短连接请求太频繁可以考虑调整内核参数net.ipv4.tcp_tw_reuse来复用这些连接不过这个优化涉及系统级参数建议先和运维确认再动。3.3 kill、systemctl 与优雅停止后端服务需要重启或停止时很多人直接kill -9 PID。这么说吧kill -9是终极大招但不应是首选。服务进程收到-9信号后没有任何机会清理资源可能丢失正在处理的任务也可能留下未释放的锁和脏数据。正确的做法是先试kill PID默认发送 SIGTERM 信号让进程自行收尾等待几秒后再检查进程是否退出没退出才考虑kill -9。如果你用的是 systemd 管理的服务那常规操作是systemctl restart 服务名、systemctl stop 服务名、systemctl status 服务名。systemctl的优点是能管理开机自启动systemctl enable查看服务日志journalctl -u 服务名这在部署 Java 或 Go 服务时非常省事。我个人在服务器上部署新服务时一定会写一个 systemd unit 文件让服务随系统启动自动拉起避免每次宕机后都要手动敲命令恢复。3.4 磁盘与内存的查看命令磁盘写满是个隐蔽坑。服务还在跑但突然报磁盘空间不足日志写不进去、临时文件创建失败。这时候用df -h查看各挂载分区的总容量、已用、可用和使用率。如果发现使用率 100%再去查找大文件du -sh *统计当前目录下各子目录的占用或者find / -size 1G -exec ls -lh {} \;找出大于 1G 的文件。清理日志时常用的truncate -s 0 /data/logs/app.log能把日志文件瞬间清空而不影响正在写入的进程句柄比直接rm日志文件更安全。直接rm一个正在被占用的日志文件文件句柄不会释放磁盘空间可能一直不回收这时候只有重启进程才能释放这个坑我踩过不止一次。内存方面先看free -h看 total、used、available 这三列。-h是以人类可读的格式显示GB 和 MB 一目了然。注意free里的 used 和 available 的含义不同available 才是估算的可用内存而 used 里包含缓存buff/cache。Linux 会尽量把空闲内存用作文件缓存这是正常机制不代表内存不足。如果 available 特别低再配合top看看哪个进程占用高。Java 应用要看堆内存情况就得用jstat或jmap这些 JVM 工具这里不多展开。4. 网络排查与远程操作让服务交互更顺畅4.1 ping、telnet、nc从网络连通性到端口连通性后端联调的时候最常遇到的问题是“我这边调不通你的服务”。先别急着怀疑代码按网络层次一步一步排除。第一步ping 目标IP。这个命令发送 ICMP 探测包看目标主机是否可达、延迟多大。ping通只代表主机在线不代表端口可访问。第二步才是关键测试端口连通性。老的telnet 目标IP 端口能测 TCP 端口是否开放输入命令后如果显示Connected to ...说明端口可达如果卡住不动或者报Connection refused那就要看是防火墙拦截、服务没监听还是网络路由问题。Connection refused多半是服务确实没起来Operation timed out则大概率是防火墙丢包或网络不通。很多新服务器默认没装 telnet最小化安装更是连 nc 都没有。这时候可以用nc -vz 目标IP 端口-v显示详情-z只扫描端口不发送数据。这个命令的退出码也可以用在脚本里做健康检查。如果nc也没装那你还可以临时用curl -v telnet://目标IP:端口来测能连上一样有输出。方法很多但要记住目的是判断端口通不通而不是死磕某一个工具。4.2 curl接口自测和调试的万能工具curl 是后端必须熟练掌握的命令没有之一。本地测试接口、排查线上返回异常、抓响应头全靠它。最基础的是curl http://example.com/api/user直接打印响应体。加-i显示响应头加-v显示整个请求和响应交互过程包括 DNS 解析、TCP 连接、TLS 握手、请求头和响应头。看-v输出时重点观察几个阶段Connected to说明 TCP 连通SSL connection using说明 TLS 握手成功HTTP/1.1 200 OK是最终响应码。如果卡在Trying IP...和Connected之间问题大概率在网络链路。携带参数请求接口用-X POST指定方法-H添加请求头-d添加请求体。比如curl -X POST http://example.com/api/login -H Content-Type: application/json -d {username:test,password:123456}。这里的坑是-d默认会附带Content-Type: application/x-www-form-urlencoded如果你要发 JSON一定要显式加-H指定否则后端按表单解析可能拿不到参数。想要模拟带 Cookie 的会话用-b sessionidxxx想跟随重定向用-L想设置超时保护用--connect-timeout 3和--max-time 10这两个超时参数在脚本里尤其重要防止 curl 一直卡住拖垮整个脚本。4.3 SSH 与 SCP远程登录和文件传输后端服务器的操作基本都基于 SSH。ssh 用户名服务器IP登录端口非默认时ssh -p 端口 用户IP。生产环境一般建议用密钥登录而非密码配置方式是把本地公钥追加到服务器~/.ssh/authorized_keys文件里。我习惯给不同环境配置不同的 SSH 别名写在~/.ssh/config中比如写个Host test-server下面配好 HostName、User、Port、IdentityFile之后直接ssh test-server就能登录省去每次记 IP 和端口。传文件用scp。scp localfile.tar.gz userserver:/data/deploy/把本地文件推到服务器scp userserver:/data/logs/app.log ./把服务器文件拉回本地。传整个目录加-r。如果文件太大我一般先用tar打包压缩再传网络传输效率高很多。还有一个加密传文件的工具rsync支持增量同步和断点续传适合部署发布时把本地构建产物同步到多台服务器rsync -avz --progress dist/ userserver:/data/www/。-a归档模式保留权限和时间戳-v显示过程-z传输时压缩。rsync 第一次可能全量同步后面再跑就只走增量比 scp 效率高不少。4.4 用 cURL 和脚本做接口监控后端服务上线后接口可用性不能等用户投诉了才知道。我通常会写一个简单的 Shell 脚本用 curl 定时探测健康检查接口如果返回码不是 200 或者响应超时就告警。比如#!/bin/bash code$(curl -s -o /dev/null -w %{http_code} --connect-timeout 5 --max-time 10 http://localhost:8080/health) if [ $code ! 200 ]; then echo $(date) health check failed, code$code /data/logs/healthcheck.log fi-o /dev/null丢弃响应体-w %{http_code}只输出状态码写起来非常方便。再配合 crontab 每 5 分钟执行一次就是一个最基本的服务可用性监控。这个脚本的进阶版可以检查响应体里是否包含特定关键字判断服务是否处于正常业务状态而不只是进程还活着。5. 实用脚本技巧与常见问题排查实录5.1 三个后端高频场景的 Shell 脚本模板后端写 Shell 脚本最频繁的场景无非是查日志聚合、批量部署、定时清理。我分享几个能直接用的小模板。日志聚合统计最常见的是统计接口耗时。假设日志格式是2025-01-12 10:15:22 INFO request /api/user cost 120ms那么平均耗时可以这样统计grep /api/user app.log | grep -o cost [0-9]*ms | awk {sum$2; count} END {if(count0) print avg sum/count ms, count count}grep -o只提取匹配的cost xxxms片段awk 负责累加和求平均值。END块在文件读取结束后执行一次避免遍历每条记录时重复输出。这是非常典型的文本聚合写法理解了grep -o从行中摘数值、awk做统计的模式你就能套用到各种耗时、错误率统计中。批量部署脚本如果只是重复执行几条命令用简单的 for 循环即可。假设你要把本地构建好的 jar 包传到 3 台服务器并重启服务for host in 192.168.1.10 192.168.1.11 192.168.1.12; do scp app.jar user$host:/data/app/ ssh user$host systemctl restart appserver done注意别忽略set -e或set -x。set -e让脚本在遇到任何非零退出码时立即退出避免出错后继续执行造成破坏set -x打印每条命令的执行过程方便调试时看走到哪一步。脚本上线之前先在测试环境跑通人不会因为谨慎而吃亏。定时清理日志脚本也常用。比如保留最近 7 天的日志每天凌晨删除更早的文件find /data/logs -name *.log.* -mtime 7 -exec rm -f {} \;-mtime 7表示修改时间超过 7 天的文件。加上 crontab 配置0 3 * * * /data/scripts/clean_logs.sh每天凌晨 3 点执行一次。这类脚本上线前建议先改成-print而不是-exec rm把会删的文件列出来检查一遍确认没有误删风险后再放行。5.2 常见问题的排查速查表与解决思路后端在 Linux 上最常见的几个问题我整理成了一张速查表按症状、原因、命令、解决思路来写症状可能原因排查命令处理思路服务启动失败端口被占用ss -tlnp | grep 8080杀掉占用进程或改服务端口磁盘告警日志或数据文件过大df -hdu -sh *清理归档日志 / 扩展磁盘CPU 飙升代码死循环或 GC 异常topjstack PID定位线程栈看业务代码内存不足堆内存配置不合理free -hjstat -gc PID调整 JVM 参数或增加内存接口超时网络延迟 / 后端服务阻塞curl -w time_total分层压测定位链路瓶颈连接数过多频繁短连接 / 连接未释放ss -sss -tn state time_wait启用连接复用或改为长连接这些症状很多时候不是孤立的。比如磁盘告警和接口超时经常同时出现日志文件把磁盘塞满导致新日志写不进去数据库落盘也变慢接口雪崩式超时。这时候不要一头扎进应用日志里查代码先看磁盘的df -h就能立刻发现根因。5.3 后端使用 Linux 命令的常见坑第一个坑是rm -rf误删。删文件之前确认路径用相对路径别用cd /后拼路径。我自己的习惯是删目录前先用ls看一下确认要删的是预期的内容删除命令写成/bin/rm -rf /data/tmp/结尾带斜杠避免因为手滑把同级或上级目录误删。第二个坑是命令超时导致脚本假死。很多人写自动部署脚本时直接ssh userhost cd /data sh deploy.sh但 ssh 执行远程命令时如果远程命令里还有交互式提示或长时间等待本地 ssh 进程会一直挂着部署流程卡死。解决办法是加-o ConnectTimeout3和-o BatchModeyes参数禁止交互式密码输入配合超时时间让脚本快速失败而不是无限等待。第三个坑是环境变量差异。手动在终端执行命令没问题但用 crontab 跑脚本时经常报command not found比如在脚本里写了java -versioncrontab 环境里 PATH 没有包含 JDK 的 bin 目录。解决方式是在脚本开头显式export PATH/usr/local/jdk/bin:$PATH或者直接用绝对路径调用命令。一个小习惯能省掉很多半夜被 oncall 叫醒的经历。第四个坑是管道命令的返回码。Shell 默认返回管道中最后一个命令的退出码。比如curl -s http://xxx | grep success如果curl失败了但grep没匹配到任何内容grep返回 1脚本里用$?判断得到的是 grep 的结果而不是 curl 的结果导致误判。想拿到第一个命令的真实退出码可以用set -o pipefail它会让管道中任何一个命令失败都返回失败状态。这个在写健壮脚本时非常关键。5.4 从命令到工具链值得花时间打磨的方向熟练掌握这些常用命令只是第一步后端要提升效率还可以往几个方向深入。一是把命令组合成脚本存放常用的故障排查流程比如一键收集系统信息CPU、内存、磁盘、网络连接数、最近日志错误故障时先跑一轮收集省去重复敲命令的时间。二是学习jq解析 JSON 输出现在很多工具和接口都返回 JSON比如 curl 调的 API 结果、docker inspect 的输出用 jq 可以像 awk 处理文本一样处理 JSON 结构脚本处理数据方便太多。三是熟悉tmux或screen服务器上长时间跑任务、断线后会话不丢这个对远程操作非常实用我通常会在服务器上开一个tmux会话把打包、编译、部署这类耗时长且中断风险高的操作放进去即使本地 SSH 断了远程任务也不会被 SIGHUP 信号打断。我个人的感受是Linux 命令不是靠背出来的是靠一次次实际排查喂出来的。你每踩过一个坑对命令的边界理解就更深一层。与其收藏一堆“常用命令大全”不如自己动手把服务部署一遍、把故障模拟一遍、把日志统计一遍。命令只是工具解决问题的思路才是后端工程师的核心能力。上面这些内容是我自己在日常开发中反复用到的东西希望能给你的工作流带来一点启发。