Linux 系统故障排查全流程

2次阅读

journalctl -u 服务名 -n 50 -e 查看完整日志,因 systemctl status 默认仅显示10行且截断;磁盘满时用 lsof +l1 找已删仍被占用文件;ssh连不上需检查监听地址、防火墙、selinux及非标端口放行;oom触发需查 dmesg 和 memavailable。

Linux 系统故障排查全流程

systemctl status 显示 failed 但没报具体错误

服务启动失败时,systemctl status 只显示 failed 状态,日志被截断或没刷出来,根本看不出哪行出问题。
真正有用的日志其实在 journalctl 里,而且得加参数才看得全。

  • 先执行 journalctl -u <service-name> --since "2 minutes ago"</service-name>,把时间范围锁紧,避免翻几百页日志
  • 如果服务刚启过又崩了,用 journalctl -u <service-name> -n 50 -e</service-name> 直接跳到最新 50 行并定位末尾
  • 注意:systemctl status 默认只显示最近 10 行日志,且会省略关键堆栈(比如 Python 的 Traceback 被截成 [...]
  • 某些服务(如 nginx)自身日志在 /var/log/nginx/Error.logjournalctl 不会自动合并,得手动查

df 显示磁盘已满,但 du -sh /* 加起来远小于总量

这是典型的“文件被删但进程还在写”的情况——inode 没释放,空间实际被占着,df 算它,du 却看不见。

  • 运行 lsof +L1,列出所有已删除但仍被打开的文件(状态为 DEL 的那行)
  • 重点关注 COMMAND 列,比如 rsyslogdjava 进程长期持有旧日志句柄
  • 临时解法:重启对应进程(systemctl restart rsyslog),别直接 kill -9,可能丢数据
  • 长期预防:配置 logrotate 时加上 copytruncate,或确保应用支持 SIGHUP 重载日志文件

ssh 连不上,ss -tlnp | grep :22 却显示端口监听正常

端口开着 ≠ 你能连上。防火墙、SELinux、监听地址绑定、甚至 sshd 配置里的 AllowUsers 都可能拦在半路。

  • 先确认监听的是不是 0.0.0.0:22 而不是 127.0.0.1:22——后者只允许本地连
  • 检查 iptablesnftables:运行 iptables -L input -n --line-numbers,看有没有 DROP 规则挡在 ACCEPT 前面
  • SELinux 拦截时,sshd 日志里通常有 avc: denied,临时关它验证:setenforce 0(别忘了之后 setenforce 1
  • 如果用非标准端口,确保 firewall-cmd --list-ports 里真放行了,别只改了 sshd_config

dmesg 里出现 Out of memory: Kill process

OOM killer 被触发不是内存不够用的表象,而是内核判定某个进程吃太多、必须杀来保系统——这时候查 free -h 可能还剩 1G,但那是假象。

  • dmesg -T | grep -i "killed process" 找到被干掉的进程名和当时内存分配上下文
  • 重点看 MemAvailable: 值(cat /proc/meminfo),它比 freeavailable 更准,反映真正可立即分配的内存
  • 常见诱因:Java 应用没设 -Xmx,容器没配 memory limit,或内核 vm.swappiness 设太高导致频繁换页
  • 别急着加 swap,先用 ps aux --sort=-%mem | head -10 抓内存大户,再结合 pmap -x <pid></pid> 看它到底在用哪些段

事情说清了就结束。排查时最常漏的是时间维度(比如日志没限定范围)、权限维度(比如普通用户看不到 journalctl 全量)、还有“看起来在运行其实早挂了”这种状态错觉。

text=ZqhQzanResources