做一个后端开发,和服务器打交道是每天的必修课。不管你是刚入行还是在带项目,花五分钟敲一条命令就能定位问题,总比打开各种监控面板反复切换省事得多。我经常跟团队里的小伙伴说,Linux命令这东西,不需要背十几页手册,把高频场景吃透,遇到问题知道该用什么工具、去哪看状态,就已经超过大部分人了。这篇文章我就把后端日常开发中真正常用的命令梳理一遍,结合我自己的使用习惯和踩过的坑,给出一套能直接上手的清单。
1. 先理清楚:日常排查和部署,我们到底需要命令做什么
1.1 后端开发命令使用的三个高频场景
后端开发的日常工作,大体上可以拆成三个场景:看日志找问题、看资源状态做判断、传文件跑任务。这三个场景几乎覆盖了90%的命令使用需求。
先说看日志。接口报错了、数据对不上了、任务没跑完,第一反应是去服务器看日志文件。这时候你会用到tail、grep、awk,结合less翻页,配合find或ls确认日志文件的位置和滚动情况。我见过不少同事遇到线上问题第一件事是打开某监控平台点来点去,其实直接登录服务器敲一条tail -f加grep组合,几秒钟就能看到实时报错,比图形界面快得多。
再说资源状态。接口变慢、内存飙升、磁盘写满,这种问题光看应用日志往往不够,需要结合系统层面确认是不是资源瓶颈。free看内存、top看CPU和负载、df看磁盘、iostat看IO、ss看连接数,这些命令组合起来能在几分钟内判断出问题方向。尤其是半夜收到告警的时候,依赖这些命令快速定位,比等监控平台刷新靠谱得多。
最后是传文件和跑任务。发版要传jar包或代码包,服务器之间要同步数据,长时间跑脚本要保证退出终端后不中断。这里会用到scp、rsync、tar、nohup、tmux。很多人只知道scp一个文件怎么传,但遇到大目录、断点续传、后台运行这些需求,只靠一条scp是不够的。
1.2 我为什么建议先掌握命令思维而不是背参数
很多初学者喜欢把命令的参数背下来,但我的经验是,真正该记住的是"什么场景下用什么命令",参数可以随时查。
举个例子,ps和top都能看到进程信息,但侧重点不同。ps是快照,适合抓当前某个进程是否存在、PID是多少;top是动态刷新,适合观察CPU和内存的实时变化。明白了这一点,你就不容易在"要看CPU持续飙高"的场景下还去敲ps -ef傻等结果。
再比如,du和df都跟磁盘有关。df看的是分区级别的使用率,df -h一条命令直接告诉你哪块盘满了;du看的是目录级别的大小,适合找出谁占的空间。很多人磁盘告警时只知道df -h,却不知道用du -sh *去逐层排查哪个目录把人逼疯占满了空间。
所以这篇文章的定位不是命令大全,而是"遇到什么情况敲什么命令"的实用地图。你不需要背,也不建议背,跟着场景走一遍,自然就熟了。
2. 日志排查三板斧:tail、grep、awk的实际组合打法
2.1 tail与grep组合:实时追踪和关键字过滤
日志排查里我用得最多、也是优先级最高的命令组合,就是tail加grep。
tail -f /opt/app/logs/app.log | grep --line-buffered "ERROR"这条命令实现了两个目标:实时追加文件内容,同时只保留包含ERROR的行。--line-buffered这个参数很关键,因为管道再组合时,grep默认会进行块缓冲,日志输出不及时。加上这个参数后可以实时看到新日志,不会卡着半天不吐内容。
如果只是从历史日志里查某个时间段或某个关键字的记录,用grep直接过滤更合适:
grep "订单号123456" /opt/app/logs/app.log嫌输出太多,加-C带上下文是个好习惯:
grep -C 5 "订单号123456" /opt/app/logs/app.log-C 5表示同时打印匹配行的前后5行。这个效果在排查报错原因时特别有用,因为只看报错那一行往往不知道前因,配合上下文才能还原完整的处理链路。
另外提一下less的配合。如果日志文件很大,grep结果几百上千行,直接打印会刷屏,最好的方式是先管道给less:
grep "ERROR" /opt/app/logs/app.log | less在less里可以按Shift+G跳到底部,也可以输入/关键字进行二次搜索,还能用n循环匹配,体验比直接把内容打印在终端里好太多。说句实在话,less这个工具我用了好几年才发现它的好,一旦用上就回不去了。
2.2 awk与sed:从日志里提取字段,批量修改文本
grep负责筛选行,awk则能把行拆成字段进行统计和提取。线上日志常见格式是时间 级别 [线程名] 类名 - 消息这种空格间隔结构,如果你只想知道某个接口的响应耗时,可以直接用awk取对应列。
比如日志格式类似:
2024-11-10 10:00:01 INFO [http-nio-8080-exec-3] com.demo.OrderService - createOrder cost=125ms想统计某个服务的平均耗时,可以做一把简单的算术:
grep "createOrder cost" app.log | awk '{sum += $6} END {print sum/NR}'这里$6是第六列,即cost=125ms这个字段。sum是累加变量,NR是行数。注意字段里带cost=和ms,严格说要先用gsub把非数字去掉再做累加,但日常快速估算时,直接取列做平均也够看出量级了。想更精细的话,可以这样写:
grep "createOrder cost" app.log | awk '{gsub(/cost=|ms/,"",$6); sum+=$6} END {print sum/NR}'gsub会把第六列中的cost=和ms替换为空,剩下纯数字再做累加,得到的结果就是平均毫秒数。
sed则更适合批量替换和文本修改。比如临时把配置文件里的端口从8080改成8081,然后重新加载,一键执行:
sed -i 's/8080/8081/g' /opt/app/config/application.yml用了-i会直接修改文件,这个参数在我刚工作时经常忘了加,导致命令执行完没有任何变化,大家如果发现sed改了没生效,先检查是不是少了-i。另外,执行线上配置变更前,建议先复制一份配置做备份,否则改坏了想恢复就很麻烦。
2.3 实战案例:一个"接口偶发超时"的完整定位过程
聊点实际发生的排查过程。有段时间某个查询接口偶发超时,监控面板能看到超时的告警,但复现不了。我当时的排查思路是这样的:
第一步,先看异常时刻的日志上下文。
grep "查询超时" /opt/app/logs/app.log | tail -20如果报错里有具体耗时,继续往下查前面的操作记录,确认是不是慢在数据库查询上。
第二步,把日志按关键字切片,拉出超时接口的完整处理链路。
grep -E "queryOrder|db_query|timeout" app.log | grep "10:30:1"用grep -E做正则匹配多个关键字,再用第二个grep限定时间范围,快速还原这段时间的调用链路。
第三步,怀疑是数据库连接池不够导致等待,这时候看应用的日志不一定看得出来,但系统层面的连接数、活跃线程数会有特征。用top看一眼进程状态,再用ss -s看socket使用情况,配合dmesg查看内核日志有没有丢包或TCP重传的记录。
这个案例想表达的是,命令本身没有多复杂,真正值钱的是排查顺序:先日志缩小范围,再系统状态确认瓶颈,而不是一上来就试一堆工具。
3. 资源监控:把服务器的"体检报告"读明白
3.1 CPU与内存:top和free的正确打开方式
服务器卡顿,第一步永远是看top:
toptop的输出信息量很大,但核心就几块。最上面是负载均值load average: 0.3, 0.1, 0.1,三个数字分别代表1分钟、5分钟、15分钟的平均负载,如果负载接近CPU核数,说明系统已经满负荷运转。然后是进程列表,按CPU使用率排序,默认每几秒刷新一次。
如果只想看某类进程的状态,用top -p指定PID:
top -p 12345或者加上用户过滤,只看某个服务账号的进程:
top -u appuserfree -h看内存更直观:
free -h输出里有total、used、free、buff/cache几列。需要强调的是,Linux会把空闲内存用作缓存,所以free那一列小不代表内存真的不够。真正要关注的是available这一列,这才是系统实际可用于分配新内存的量。如果available长期低于总内存的20%,就该考虑调整JVM堆大小或者增加内存了。
CPU方面还有一个经常被忽略的点:top里看到的hi和si分别代表硬件中断和软件中断。如果si数值一直很高,往往是网络包处理不过来,此时应用层再正常,整体性能也上不去。
3.2 磁盘与IO:不能只盯着df,还要会看iostat
磁盘满了是后端最容易踩到的故障之一。报警来得最频繁的往往就是磁盘使用率超过80%或者90%。
df -h用于快速了解整体情况:
df -h如果某块盘满了,下一步就是要找到底是哪些目录在占空间:
du -sh /opt/app/* /home/* /tmp/* 2>/dev/null | sort -rh | headdu -sh统计目录大小,sort -rh按数字大小倒序排列,加上head只看最大的几个。这样一级一级往下钻,很快能找到是日志目录、临时文件还是数据库数据文件占据了空间。
磁盘的使用率只是静态维度,如果是IO性能问题,需要用iostat看动态情况:
iostat -x 1 5每秒刷新一次,连刷5次。重点关注%util列和await列。%util接近100%说明磁盘已经忙不过来,await过高说明IO响应延迟大。结合应用日志里数据库查询慢的现象,基本就能确认瓶颈在磁盘层。
3.3 网络连接状态:ss与netstat怎么选
看网络连接,老派做法是用netstat,现在的Linux发行版可能默认没有装这个包,我一般直接用ss:
ss -lntp这条命令列出所有监听状态的TCP端口,并显示对应的进程PID和进程名。排查"端口被占用""服务没起来但是端口还在"这类问题非常方便。
查看本国连接数,可以按状态统计:
ss -s输出里能看到当前总连接数、以及estab、time_wait、close_wait等状态的数量。如果time_wait的连接数以万计,说明服务短连接请求量很大,连接回收有点跟不上;如果close_wait飙升,说明应用没正确关闭连接,这时候首先要查代码里的连接池或HTTP客户端配置,而不是折腾内核参数。
4. 文件传输与部署:上线过程中绕不开的几件事
4.1 scp与rsync:传文件如何选
部署发版,最基础的文件传输是scp:
scp app.jar user@server:/opt/app/该命令把本地文件复制到远程目录。传整个目录用-r:
scp -r ./dist user@server:/opt/web/scp的劣势在于大目录传输容易中断且不支持断点续传,传应用包一般没问题,但传到一半网络抖动就得从头再来。
如果目录大、文件多,我优先选择rsync:
rsync -avz --progress ./dist/ user@server:/opt/web/参数含义是:-a归档模式保留权限和软链,-v显示过程,-z传输时压缩,--progress显示进度。最大的优势是只传差异文件,本地和远端文件相同部分不会被重新传输,对重复发版场景特别友好。
线上环境如果没有rsync,先装一个或者用scp过渡。我个人建议新项目直接在基础环境里预装rsync,后端的发版脚本用起来会很顺手。
4.2 tar打包与解压:别记混了c和x
上传一堆配置文件或者备份日志时,打包能减少文件数量还保留目录结构。解压和压缩命令的核心区别就两个字母:
# 打包压缩 tar -zcvf app_backup.tar.gz /opt/app/logs/ # 解压 tar -zxvf app_backup.tar.gz -C /tmp/restore初学者最容易把c和x搞混,我提供一个记忆方式:c就是create,创建包;x就是eXtract,往外取文件。其余参数中z是gzip压缩,v显示过程,f后面跟文件名。解压到指定目录用-C指定路径,不指定就解压到当前目录,容易把文件散乱在当前目录,建议每次都写明-C。
压缩时如果想排除某个子目录,使用--exclude:
tar -zcvf app_backup.tar.gz --exclude='/opt/app/logs/*.tmp' /opt/app/这条命令常用于备份整个应用目录但排除临时文件,避免备份包过大。
4.3 服务器上跑长任务:nohup和tmux的取舍
想在服务器上跑一个持续几分钟甚至几小时的任务,比如数据清洗脚本、批量发送消息,最直接的方式是:
nohup python3 clean_data.py > run.log 2>&1 &nohup让进程忽略挂断信号,&放后台运行,> run.log 2>&1把标准输出和错误输出都写入文件。这样即使终端关闭,任务也能在后台继续执行。
但nohup有一个不够方便的地方:如果你想回头查看任务运行状态、交互式地输入内容或执行多步操作,它做不到。此时用tmux更合适:
tmux new -s data_clean # 进入会话后,执行目标任务 python3 clean_data.py # 按 Ctrl+b 然后按 d 退出会话,但任务持续运行 tmux attach -t data_clean # 重新回到会话tmux可以理解为一个驻留在服务器上的虚拟终端。任务在执行过程中可以随时断开连接,重新登录后再attach回去继续看输出和交互,中间不需要担心终端断开导致任务终止。对于需要分阶段确认结果的脚本任务,这个体验比nohup好很多。
5. 实战经验:命令虽然常用,这几个坑还是得小心
5.1 通配符误删文件,警惕手滑删错
后端同学在清理日志或临时文件时很容易犯的一个错是通配符写错位置。比如:
rm -rf /opt/app/logs/*.log如果logs目录路径判断错了,或者通配符没有匹配到预期文件,危险系数极高。我用rm有一条原则:先ls再rm,先列出匹配内容确认无误后再执行删除操作。
ls /opt/app/logs/*.log确认列表里都是预期文件后,再替换成rm执行。更稳妥的做法是对目录路径使用全路径,避免相对路径和环境变量导致删错位置。
5.2 kill与kill -9的差异:优雅关闭优先
kill命令默认发送的是TERM信号,应用收到后可以做优雅关闭,比如释放连接池、保存中间状态。kill -9发送的是KILL信号,由内核直接强制终止进程,应用没有机会做任何清理。
正确的关闭顺序应该是先kill PID,等几秒看进程是否退出;如果超时未退出,再考虑kill -9:
kill 12345 # 等待几秒后检查是否还存在 ps -p 12345 kill -9 12345特别是数据库迁移脚本、消息队列消费者这类有状态任务,直接被kill -9容易留下脏数据或重复消费的问题,能优雅关闭就尽量优雅关闭。
5.3 xargs与管道:文件路径里有空格就尴尬了
用管道组合命令时有一个常见的坑,比如想把某目录里的文件都传走:
find /opt/app -name "*.xml" | xargs scp {} user@server:/tmp/如果文件名里带空格或特殊字符,xargs默认按空格拆分,就会把一条路径拆成多条,引发报错。
更稳妥的做法是使用find的-print0配合xargs -0:
find /opt/app -name "*.xml" -print0 | xargs -0 -I {} scp {} user@server:/tmp/-print0让find输出用空字符分隔路径,xargs -0按空字符识别,这样就算文件名里带空格也不会有问题。这个细节平时用不太上,但一旦遇到中文文件名或带空格的文件目录,就知道有多救命了。
6. 高频命令速查表:我整理在日常笔记里的那一份
6.1 按场景分类的速查命令
下面这张表是我在个人笔记里常备的,团队新人入职我也会发一份。谈不上什么高大上,但真的很实用。
| 场景 | 命令 | 说明 |
|---|---|---|
| 实时看日志 | tail -f app.log | 跟踪日志输出 |
| 过滤关键字 | grep "ERROR" app.log | 按关键字筛行 |
| 带上下文过滤 | grep -C 5 "ERROR" app.log | 匹配前后各行输 |
| 统计字段取舍 | awk '{print $2}' | 提取第二列 |
| 看内存 | free -h | 查看内存使用情况 |
| 看磁盘 | df -h | 看分区使用率 |
| 找大目录 | `du -sh /xxx/* | sort -rh | head` |
| 看进程 | ps -ef | grep java | 找到应用进程 |
| 动态监控 | top | 实时CPU内存 |
| 看监听端口 | ss -lntp | 查看端口与PID |
| 文件复制 | scp file user@host:/path | 单文件传输 |
| 差异同步 | rsync -avz | 目录增量同步 |
| 打包压缩 | tar -zcvf xx.tar.gz path | 打包并压缩 |
| 解压 | tar -zxvf xx.tar.gz -C /dir | 解开包到指定目录 |
| 后台长任务 | nohup cmd > log 2>&1 & | 断开不中断 |
| 虚拟终端 | tmux new -s name | 可重新接入会话 |
这些命令覆盖了我日常工作的绝大多数需求。遇到新命令我不会强行记,而是先看场景,再查man帮助或--help,用熟了以后就知道参数该放在哪里了。
6.2 开发机与生产机的命令使用差异提醒
最后提醒一下开发环境和生产环境的差异。开发机上操作可以随意,生产机上执行命令要格外谨慎。
在生产服务器上,我只读状态下安全,例如ps、top、free、ss、grep、tail这类命令没问题;但是涉及修改状态的命令要三思而后行,比如rm -rf、sed -i、kill -9、chmod、mv,这些命令执行前建议先确认路径、备份文件、跟同事沟通或者放在变更窗口内操作。
我自己的习惯是,生产环境执行任何可能产生影响的命令前,先在终端里把命令打印出来发给团队评审或者自己复核一遍,再把路径换成绝对路径,加上echo先跑一遍确认。养成这个习惯能避开很多本来不必要的事故,毕竟后端开发要稳定,靠的不是一时的手速,而是每一步都有把握的操作。
Linux命令是后端开发的基本功,但基本功不等于天天背手册。把它融入到具体的工作流里,多踩几次坑、多用几次排查实战,回头自然就掌握了。上面整理的这些命令和思路,都是我实际项目中反复用到、验证过的,希望能给你的日常开发和排障提供一点参考。