接手一台运行多年的Centos服务器,最怕的不是性能瓶颈,而是服务毫无征兆地挂掉。业务中断,监控告警响个不停,这时候需要的不是理论,而是能立刻上手的排查路径和恢复手段。Centos 7 虽然已进入生命周期的尾声,但大量生产环境仍在运行,其 systemd 体系下的故障排查逻辑与 Centos 6 的 SysVinit 有本质区别。以下内容直接聚焦于服务无法启动、异常退出、端口不通、资源耗尽这四类高频故障的硬核处理流程。

快速判定故障范围:服务、系统还是网络

登录服务器后,不要盲目重启。先用 systemctl status [服务名] 看一眼输出。状态若为 inactive (dead),说明服务根本没跑;若为 active (exited),往往是配置错误导致进程一启动就退出;若为 failed,直接查看系统日志。同时用 ps aux | grep [进程名] 交叉验证,避免 systemd 状态滞后。如果进程存在但端口不通,用 ss -tlnp 或 netstat -tlnp 确认监听地址,注意区分 127.0.0.1 和 0.0.0.0,很多故障仅仅是因为服务只监听了本地回环地址。网络层排查用 telnet [IP] [端口] 或 nc -zv [IP] [端口] 从外部测试,快速界定是服务本身没起来还是防火墙拦截。

精准读取日志:从海量信息中抓取关键报错

journalctl -u [服务名] -n 50 --no-pager 是 systemd 下最常用的命令,直接输出最近50行日志。遇到服务启动失败,优先看日志尾部带有 "error"、"failed"、"cannot" 的行。对于传统写入 /var/log/messages 或 /var/log/secure 的日志,用 tail -f 实时跟踪,同时另开一个终端尝试启动服务,观察输出的变化。如果日志中大量出现 "cannot allocate memory",别急着加内存,先用 free -h 看内存使用,再用 top 按 M 排序找内存大户。如果日志提示 "permission denied",重点检查 SELinux 上下文和文件权限,ls -lZ 查看 SELinux 标签,getenforce 确认当前模式,临时用 setenforce 0 关闭后重启服务,若恢复正常则说明是 SELinux 策略问题,需用 audit2allow 生成策略模块而不是永久关闭。

端口冲突与依赖服务检查

服务启动时若报 "address already in use",用 ss -tlnp | grep [端口号] 找出占用进程。如果占用进程是合法服务,需要修改端口配置;如果是残留的僵尸进程,直接 kill -9 清理。很多服务依赖数据库或缓存先启动,Centos 7 中应在 service unit 文件里用 After= 和 Requires= 声明依赖,但老旧的 SysVinit 脚本往往缺失。遇到依赖类故障,手动按顺序启动:先确认网络服务 network.target 正常,再启数据库如 mariadb 或 redis,最后启应用服务。用 systemctl list-dependencies [服务名] 可以反向查看依赖树。

资源耗尽类故障的深层排查

CPU 飙高时,top 看 %CPU 排序,记录 PID 后用 strace -p [PID] 跟踪系统调用,看进程在疯狂执行什么操作。如果是 Java 应用,用 jstack [PID] 导出线程堆栈,结合 top -H -p [PID] 找到占用最高的线程 ID,转换成十六进制后在堆栈中定位具体代码行。磁盘 I/O 瓶颈用 iostat -x 1 查看 %util 和 await,若某块盘持续 100%,用 iotop 找出读写最凶的进程。文件句柄耗尽也很常见,lsof -p [PID] | wc -l 查看进程打开的文件数,ulimit -n 查看限制,若超出则修改 /etc/security/limits.conf 并重新登录生效。inode 耗尽用 df -i 检查,如果 /var 或 /tmp 的 IUse% 达到 100%,用 find /var -xdev -type f | wc -l 确认小文件数量,通常是因为邮件队列或 session 文件堆积。

Systemd 服务单元修复与调试

当 systemctl start 失败但命令行直接运行启动脚本却正常,问题多半出在 unit 文件。systemctl cat [服务名] 查看完整配置,重点检查 ExecStart 的路径是否绝对路径、User 和 Group 是否存在、EnvironmentFile 引用的环境变量文件是否可读。修改 unit 文件后必须执行 systemctl daemon-reload。如果服务启动后立即退出,在 unit 文件的 [Service] 段添加 Restart=on-failure 和 RestartSec=5s 实现自动重启,但要注意防止无限重启循环。调试时可将 Type=simple 改为 Type=forking 或 oneshot,匹配实际进程行为。对于需要特定工作目录的服务,用 WorkingDirectory 指定。

内核参数与安全模块的隐蔽影响

某些高并发服务在压力下突然崩溃,日志中毫无痕迹,需要检查内核日志 dmesg | tail -50。若出现 "Out of memory: Kill process",说明 OOM Killer 介入了,用 grep -i "killed process" /var/log/messages 查看被杀进程详情。调整 vm.overcommit_memory 和 vm.swappiness 可以缓解,但根本解决是优化应用内存或增加物理内存。SELinux 的隐蔽阻断不会直接报错给服务,而是记录在 /var/log/audit/audit.log 中,用 ausearch -m avc -ts recent 查看最近的拒绝事件。防火墙 firewalld 的 rich-rules 或 direct rules 也可能只允许特定源 IP 访问,用 firewall-cmd --list-all 全面检查。

实战级故障修复流程

面对一台宕机的服务器,标准操作序列是:先确认物理机或虚拟机是否正常运行,用 ping 和 ssh 测试连通性;登录后执行 uptime 看负载,dmesg 看内核报错,df -h 看磁盘,free -m 看内存;然后 systemctl list-units --state=failed 列出所有失败的服务,针对每个失败服务执行 systemctl status 和 journalctl 排查;如果是 Web 服务,用 curl -I http://localhost 从本机测试,排除外部网络因素;最后根据日志指向,修复配置、释放资源或调整权限,再次启动服务并验证。整个过程中,任何修改操作前先备份原文件,用 cp -a 保留属性。

预防性运维的自动化脚本思路

硬核运维不会每次都手动救火。编写一个巡检脚本,将 systemctl list-units --state=failed、df -h、free -m、uptime、ss -tlnp 等命令输出重定向到文件,配合 crontab 定时执行。设置资源告警阈值,比如当磁盘使用率超过 85% 或内存低于 200MB 时,自动发送邮件或触发 webhook。对于核心服务,编写 health check 脚本,用 systemctl is-active [服务名] 检测状态,一旦返回非 active,立即尝试重启并记录日志。这些脚本应纳入版本控制,成为团队知识库的一部分。

Centos 停更后的迁移与兼容策略

Centos 7 已于 2024 年 6 月停止维护,继续使用意味着安全漏洞无法修复。对于仍跑在 Centos 上的服务,短期方案是接入第三方安全更新源,长期必须迁移至 Rocky Linux 或 AlmaLinux 等兼容发行版。迁移前在测试环境用同样的服务栈部署,验证 systemd unit 文件、SELinux 策略、第三方仓库的兼容性。尤其注意从 Centos 7 到 Rocky 9 的跨大版本迁移,PHP、Python、OpenSSL 等基础组件版本变化巨大,服务启动脚本和依赖库路径都可能需要调整。迁移过程中保留完整的 /etc 目录备份,这是回滚的最后防线。