1. 基层操作:文件与文本处理是后端每天的体力活
后端开发跟Linux打交道,频率最高的其实不是那些花哨的性能调优命令,而是最基础的文件查看、日志追踪和文本检索。很多人觉得这些太简单,不值得专门总结,但实际上,线上问题排查的黄金十分钟,往往就耗在“找不到日志在哪”“不会快速过滤关键信息”这些看似基础的事情上。
1.1 查看文件:别只会用cat,组合拳才是常态
承接上文,文件查看虽然基础,但不同场景下工具选择完全不同。cat适合查看小文件全文,超过几百行的输出直接刷屏,根本没法看。更实用的做法是:
# 查看文件前N行,默认10行 head -n 50 app.log # 查看文件末尾N行,排查崩溃原因基本靠这个 tail -n 100 app.log # 实时跟踪日志输出,服务调试时挂一个终端专门跑这个 tail -f app.logtail -f是后端排查问题时使用频率最高的命令之一。服务报错了,先打开日志文件所在的目录,执行tail -f,然后复现问题,日志会一屏一屏地滚动,问题原因基本能看出个大概。如果日志量特别大,还可以加上grep过滤:
tail -f app.log | grep -E "ERROR|Exception"这条命令相当于给日志装了个筛子,只把错误级别的信息漏出来,不至于被海量正常日志淹没。实际工作中,我还习惯搭配--pid参数:先pgrep -f java找到进程号,再用tail -f --pid=1234 app.log,这样进程一退出,tail 命令也会自动结束,不需要手动 Ctrl+C,在自动化脚本里尤其好用。
1.2 文本检索:grep的进阶用法能救命
后端查日志绕不开grep,但很多人只会最基础的grep "关键字" 文件,效率其实很低。分享几个我实测下来非常高频的用法:
# 递归搜索某个目录下所有文件,线上日志按天切割时特别有用 grep -r "订单号20241228" /data/logs/ # 同时搜索多个关键词,用 -E 开启扩展正则 grep -E "NullPointerException|OutOfMemoryError" app.log # 显示匹配行的前后几行,看异常堆栈时必需 grep -n -A 5 -B 2 "Exception" app.log # 统计某个关键词出现的次数 grep -c "ERROR" app.log-A和-B参数是看 Java/Python 异常堆栈的利器。异常栈通常不是一行,而是十几行连续的堆栈信息,只看匹配行根本定位不到业务代码。加上-A 10把异常后面的上下文打出来,才能看到具体是哪段业务逻辑出的问题。
注意:grep 默认是区分大小写的,查日志时如果关键字大小写不确定,记得加
-i参数忽略大小写,否则容易漏掉关键信息。
1.3 文件查找:别再一条条 ls 翻目录了
项目代码、配置文件分布在多个目录,靠ls一层层进去翻显然太低效。find命令应该成为肌肉记忆:
# 按文件名查找,支持通配符 find /etc -name "*.conf" # 按时间查找,24小时内修改过的文件 find /data -mtime -1 # 按大小查找,超过500M的大文件,排查磁盘满时第一步就查这个 find / -size +500M我排查磁盘报警时,习惯先执行df -h看整体占用,再执行find /data -size +1G -exec ls -lh {} \;把大文件逐个揪出来。这里-exec的作用是找到的结果再执行一次后面的命令,最终输出文件大小,比光秃秃的路径直观得多。
2. 进程与服务管理:线上服务出问题时的第一道防线
文件操作解决的是“看什么”的问题,进程管理解决的是“谁在跑、跑没跑、挂了没有”的问题。后端开发日常部署服务、重启应用、排查僵死进程,本质都是在跟进程打交道。
2.1 查看进程:ps命令的参数组合要记牢
先看最基础的ps:
# 查看所有进程,包含完整命令行参数 ps -ef # 查找某个服务的进程号 ps -ef | grep javaps -ef输出的第二列是 PID,第八列是启动命令。实际工作中,我更喜欢用ps -aux,因为能看到 CPU 和内存占用率,快速判断哪个进程在“偷吃”资源。配合sort可以按 CPU 使用率排序:
ps -aux --sort=-%cpu | head -n 10这个命令一执行,CPU 占用最高的前十个进程立刻现形。之前遇到一次线上 CPU 飙升到 100% 的情况,就是用这条命令在几秒内定位到是一个异常的任务线程在疯狂空转,而不是盲目地去重启整个服务。
2.2 管理进程:kill的优雅与强制
搞清楚进程号之后,就要进行干预。kill命令有几个信号需要区分清楚:
# 优雅停止,让进程处理完手头的事情再退出 kill -15 PID # 强制杀死,进程无响应时兜底使用 kill -9 PID # 按进程名批量结束,慎用!会把所有同名进程全部杀掉 pkill -f "service-a"kill -15是默认信号,相当于给进程发了一个“该下班了”的通知,进程收到后可以执行清理逻辑。但有时候进程卡死了,-15根本没反应,这时候才用-9强制终止,相当于直接拔电源。
注意:
kill -9是最后的手段,不是第一选择。直接拔电源可能导致数据未落盘、文件损坏。我先用-15等 10 秒,没反应再升级为-9。
2.3 端口与连接排查:lsof和netstat
后端服务启动失败,最常见的原因就是端口被占用。排查端口占用有一套固定流程:
# 查看某个端口被哪个进程占用 lsof -i:8080 # 不带 lsof 的替代方案,通用性更强 netstat -tlnp | grep 8080lsof -i:8080输出里,PID 列直接告诉你谁占着端口。拿到 PID 后可以进一步确认进程信息:
ps -p PID -f这套组合拳我几乎每天都要用。部署新服务时,如果报“端口已经被占用”,先lsof -i:8080看是不是旧服务的残留进程,再决定是kill旧进程还是换个端口,而不是一头雾水地反复重启。
2.4 后台运行:nohup与日志重定向
后端开发经常要临时跑一个服务,但不能一直挂着终端窗口。规范的启动方式是:
nohup java -jar app.jar --spring.profiles.active=prod > app.log 2>&1 &这条命令里有两个关键点:
nohup让进程忽略终端挂断信号,终端关了进程依然在跑2>&1把标准错误重定向到标准输出,都写进同一个日志文件,否则错误信息会丢在终端里
不少新人栽在2>&1这个细节上,只写了> app.log,结果进程的各种报错直接打印在屏幕上,关掉终端后错误信息就彻底丢了,排查问题完全没有依据。
启动后建议立刻确认一下进程真的活着:
ps -ef | grep app.jar tail -f app.log3. 资源监控与系统体检:CPU、内存、磁盘、负载的四维观察
进程管理解决的是“某个具体服务”的问题,但线上故障经常是整台机器层面的,比如 CPU 被打满、内存耗尽、磁盘写满、系统负载过高。这时候需要把视角从进程拉高到整个系统。
3.1 整体负载:top命令的深度解读
top命令是系统体检的起点:
top进入交互界面后,重点看三块信息:
- 第一行的
load average,有三个数字,分别代表 1 分钟、5 分钟、15 分钟的平均负载。数字除以 CPU 核心数,超过 0.7 就该警惕了 - 第三行的
%Cpu(s),重点关注us(用户态占用)和wa(I/O 等待),wa高说明磁盘 I/O 有瓶颈 - 进程列表里按
P键可以按 CPU 排序,按M键按内存排序
top默认 3 秒刷新一次,如果想只看某个进程的资源占用,可以在交互界面按u键输入进程号,或者直接用:
top -p PID3.2 内存与磁盘:free和df的常规检查
内存和磁盘是后端服务最容易踩坑的资源瓶颈。
# 查看内存使用情况 free -h # 查看磁盘空间 df -h # 查看当前目录下各子目录占用大小 du -sh *free -h输出里有个关键概念:available才是真正可用的内存,而不是free。因为 Linux 会把空闲内存用作文件缓存(buff/cache),这部分在应用需要时可以释放,所以别看到free只有几百兆就慌,要判断available还剩多少。
磁盘这块,df -h查看的是文件系统级别的占用,du -sh *能定位到具体是哪个目录在疯狂吃磁盘。清理日志文件时,我习惯先du -sh * | sort -rh按容量排个序,再决定先清理谁。
3.3 I/O 瓶颈:iostat与iotop
CPU 和内存还好排查,I/O 问题往往藏得比较深。应用响应慢,但 CPU 和内存看着都正常,十有八九是磁盘 I/O 扛不住了。
# 查看磁盘读写速率 iostat -x 1 3 # 动态查看哪些进程在大量读写磁盘 iotop -oiostat -x的输出里重点看%util这一列,如果接近 100%,说明磁盘已经满负荷运转了。iotop -o能看到具体是哪个进程在疯狂读写磁盘,场景一般是日志写得太频繁,或者某个任务在批量刷数据。
注意:iostat 和 iotop 默认可能没安装,需要先执行
yum install sysstat(CentOS)或apt install sysstat(Ubuntu)。很多生产环境资料都提到过:问题发生时临时装工具,可能比等工具装完还急人,所以尽量在系统初始化时就把这些排查工具装好。
4. 网络排查与文件传输:后端联调和部署的必修课
后端开发离不开网络操作:接口调不通要排查连通性,服务器之间要传文件,跟数据库建连超时也要查网络。这块的命令看起来不多,但用好了能省大量沟通成本。
4.1 连通性测试:ping、telnet与nc
排查网络连通性问题,很多人只知道ping:
# 测试网络通不通 ping -c 4 192.168.1.10 # 测试某个 TCP 端口是否能连通 telnet 192.168.1.10 3306 # nc 是 telnet 的现代替代品 nc -vz 192.168.1.10 3306ping测的是 ICMP 协议,只要机器活着就会响应,但能ping通不代表端口能通。数据库连接超时、接口调不通,十有八九是端口被防火墙挡住了。用telnet 目标IP 目标端口,如果能连上会显示连接成功,如果卡住或报错,就是端口不通。
nc -vz是 telnet 的替代品,功能类似,还支持批量扫描端口范围:
nc -vz 192.168.1.10 8000-9000这个命令一次可以扫 1000 个端口,排查服务端口开放情况时非常好用。
4.2 路由与抓包:traceroute与tcpdump
跨网络调用出问题时,光靠 ping 和 telnet 还不够,需要看数据包走到哪一步被丢掉了:
# 追踪路由路径,看数据包经过哪些跳点 traceroute -n 192.168.1.10 # 抓取某个端口上的流量包 tcpdump -i eth0 port 8080 -w /tmp/capture.pcaptraceroute能看出网络在哪一跳延迟飙升,比如多次调用都卡在某一个中间 IP,那问题大概率出在这台跳板机上。tcpdump更底层,能直接看到数据包的内容和方向,排查“请求发出去了但服务端没收到”这类问题时,能在服务端抓包确认请求到底有没有到。
tcpdump我跟人联调时偶尔会用,不在生产环境轻易抓包,流量大时抓包文件会瞬间膨胀,拷走分析时记得用-w落盘,避免直接在终端刷屏。
4.3 文件传输:scp与rsync
部署代码、传输日志、备份数据,都涉及服务器之间的文件传输:
# 从本地复制到远程服务器 scp /data/app.tar.gz user@192.168.1.10:/data/ # 从远程服务器拉取文件到本地 scp user@192.168.1.10:/data/app.log /tmp/ # rsync 增量同步,适合大数据量重复传输 rsync -avz --progress /data/ user@192.168.1.10:/data/scp适合一次性传输,rsync的优势在于增量同步——只传输变更的部分,大量重复传输时效率高出几个量级。rsync -avz几个参数的含义:-a归档模式保留文件属性,-v显示过程,-z传输时压缩。
5. 快捷操作与效率习惯:从“会用”到“用好”
到这一步,基础命令基本覆盖完了后端开发日常的绝大多数场景。但命令掌握程度,拉开差距的是是否形成了高效的操作习惯。同一个任务,有人敲十几条命令查来查去,有人一条组合命令直接出结果,区别就在这里。
5.1 组合命令与管道:把多个命令串联成一条
管道符|是 Linux 命令组合的灵魂。把上一个命令的输出作为下一个命令的输入,一条命令就能完成多步操作:
# 查看日志中某个接口的平均响应时间 cat access.log | awk '{sum+=$NF; count++} END {print sum/count}' # 找出访问量最高的前10个IP cat access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -n 10 # 查看当前目录下占用空间最大的5个文件 find . -type f -exec du -h {} \; | sort -rh | head -n 5第一眼看上去可能有点唬人,拆开看每一步都很简单。比如第二条:awk '{print $1}'把访问日志的 IP 字段提出来,sort排序让相同 IP 相邻,uniq -c统计每个 IP 出现次数,sort -rn按次数倒序排列,head -n 10取前 10 个。链路清晰,一步到位。
5.2 别名与历史命令:让高频操作变成肌肉记忆
有些命令组合每次使用都要敲一长串,可以把它们配置成别名,永久生效:
# 在 ~/.bashrc 里添加 alias ll='ls -lh --color=auto' alias gps='ps -ef | grep' alias netport='netstat -tlnp | grep'配置完后执行source ~/.bashrc立即生效。gps java等价于ps -ef | grep java,netport 8080等价于netstat -tlnp | grep 8080,每天至少省几十次按键。
历史命令也有技巧:
# 搜索历史命令,输入关键字即可 Ctrl + R # 执行上一条命令 !! # 执行历史中序号为 N 的命令 !N!!的典型场景是:sudo权限不足执行失败,重新敲一遍太长,直接sudo !!搞定。
5.3 实用小技巧:从实操中沉淀的效率工具
最后分享几个零散但很高频的小技巧。
快速创建目录结构:
mkdir -p /data/app/{logs,conf,bin,backup}一条命令创建多层级目录,比mkdir逐个建高效太多。
快速返回上一个目录:
cd -在 A 目录和 B 目录之间来回切换时,cd -代替重复输入完整路径。
历史命令去重查看:
history | awk '{print $2}' | sort | uniq -c | sort -rn | head这个命令能统计你最常敲的命令,定期看一眼,就知道自己的操作习惯,也能发现哪些高频命令值得做成别名。
定时执行命令:
watch -n 2 'ps -aux | grep java'每 2 秒自动刷新一次命令输出,适合盯着某个进程的资源变化或某个日志文件的增长。
6. 排查实录:一次“服务假死”问题的完整命令链
说了这么多散点命令,最后用一次实际排查案例把整个流程串起来。某次线上反馈,某个服务接口响应时间从 50ms 飙升到 5 秒,但没有完全不可用。
第一步,登录服务器先看整体负载:
top看到load average到了 8.5,而机器只有 4 核,负载明显异常。进程列表里有个进程 CPU 占用到了 300%(多核),记下 PID。
第二步,确认这个进程是不是我们的服务:
ps -ef | grep PID grep -v grep确认是核心业务服务的进程。
第三步,查看日志定位具体问题:
tail -n 500 app.log | grep -E "Exception|ERROR" | tail -n 50看到频繁出现“连接池获取连接超时”的报错,基本判断是数据库连接池被打满了。
第四步,查看数据库连接情况:
netstat -tlnp | grep 3306发现大量TIME_WAIT状态的连接,说明应用频繁创建和断开数据库连接,连接复用机制没有生效。
第五步,查数据库服务的连接数上限配置,发现连接数配置偏小,而应用侧连接池大小配置过大,两者不匹配导致连接池等待。
最终解决方案是调整连接池大小,同时优化代码里部分未能正确释放连接的逻辑。整个排查过程用时约 15 分钟,全部靠的是最基础的top、ps、tail、grep、netstat,并没有任何高深命令。
这个案例想说明一件事:后端排查 Linux 问题,真正的瓶颈从来不是命令不够多,而是能不能根据症状快速选对命令、看懂输出、串联线索。把上面这些命令熟练到肌肉记忆的程度,遇到线上问题才不会慌。
我个人经验是,Linux 命令的学习不要追求“背全”,而是把日常最高频的二三十个命令用熟、用透,理解每个输出字段的含义,再配合管道组合出适合自己业务的快捷命令。时间长了,这些工具就会像吃饭喝水一样自然,那时候你就不再需要看任何命令手册了。