Linux SSH连接故障排查与修复过程分享
作者:姜太小白
这篇文章主要介绍了Linux SSH连接故障排查与修复过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
问题现象
- 初始错误:
SSH protocol handshake error, Socket error: Connection reset by peer - 后续在服务器端执行命令时出现:
-bash: fork: retry: Resource temporarily unavailable - 根本原因:系统进程数(PID)耗尽,无法创建新进程(包括 SSH 登录所需的 shell)。
排查与修复步骤(按时间顺序)
1. 紧急恢复系统创建进程的能力
目的:临时调高系统允许的最大 PID 数量,使系统能再次 fork 新进程。
# 临时修改内核参数(立即生效,无需重启) echo 1000000 > /proc/sys/kernel/pid_max # 检查当前用户进程数限制(可选) ulimit -u # 若限制过小,可临时解除 ulimit -u unlimited
2. 统计各用户进程数量,定位异常
目的:找出哪个用户占用进程数最多。
ps -eo user=|sort|uniq -c|sort -nr
输出:
28168 root
28148 oracle
58 grid
...
发现 root 和 oracle 用户各有约 2.8 万个进程,远超正常范围。
3. 进一步统计每个用户下各命令的进程数量
目的:确定具体是哪个程序(COMMAND)造成了进程爆炸。
# 统计 root 用户各进程数量(取前10) ps -U root -o comm --no-headers | sort | uniq -c | sort -nr | head -10
输出(示例):
52 bioset
51 kdmflush
7 ext4-rsv-conver
6 sshd
5 mingetty
4 bash
4 UsmGeneral
3 udevd
3 oks_rbld
3 java
root 用户下未见异常,数量可控。
# 统计 oracle 用户各进程数量(取前10) ps -U oracle -o comm --no-headers | sort | uniq -c | sort -nr | head -10
输出:
27436 sendmail
27436 crond
558 postdrop
115 oracle
18 server
18 replicat
10 extract
1 sshd
1 oraagent.bin
1 ggsci
锁定元凶:oracle 用户下堆积了约 2.7 万个 sendmail 和 2.7 万个 crond 进程,完全失控。
4. 清理异常进程
目的:终止这些失控进程,释放 PID 资源。
# 杀掉 oracle 用户下所有 sendmail 进程 pkill -u oracle sendmail # 杀掉 oracle 用户下所有 crond 进程 pkill -u oracle crond # 若上述无效或仍有残留,可强制终止该用户所有进程(注意:会中断 Oracle 数据库) pkill -9 -u oracle
5. 验证清理效果
# 查看当前总进程数 ps -e | wc -l # 分别查看各用户进程数 ps -U root | wc -l ps -U oracle | wc -l
进程数应降至正常水平(通常几百到几千)。
6. 根除病因——检查 oracle 用户的定时任务
目的:防止重启后问题复现,因为大量 crond 进程通常来自循环执行的 cron 任务。
# 查看 oracle 用户的 crontab crontab -u oracle -l # 也可直接查看 cron 文件 cat /var/spool/cron/oracle
发现异常任务(如频繁调用 sendmail 或死循环脚本),立即注释或删除相应行。
7. 永久固化系统配置(避免重启后再次耗尽)
目的:将临时修改写入配置文件,使系统重启后仍保持较大的 PID 上限和用户进程限制。
# 永久修改内核最大 PID 数 echo "kernel.pid_max = 1000000" >> /etc/sysctl.conf sysctl -p # 永久解除(或调高)用户进程数软硬限制 echo "root soft nproc unlimited" >> /etc/security/limits.conf echo "root hard nproc unlimited" >> /etc/security/limits.conf echo "oracle soft nproc unlimited" >> /etc/security/limits.conf echo "oracle hard nproc unlimited" >> /etc/security/limits.conf
8. 重启 SSH 服务并验证连接
目的:确保 SSH 服务状态正常,并能接受新连接。
# 重启 SSH 服务 systemctl restart sshd # 从另一终端尝试 SSH 连接,确认成功
关键命令速查表
| 步骤 | 命令 | 作用 |
|---|---|---|
| 紧急恢复 | echo 1000000 > /proc/sys/kernel/pid_max | 临时调高 PID 上限 |
| 查看总进程数 | ps -e | wc -l | 统计全部进程数 |
| 统计各用户进程 | ps -eo user=|sort|uniq -c|sort -nr | 找出异常用户 |
| 统计某用户各命令 | ps -U oracle -o comm --no-headers | sort | uniq -c | sort -nr | head -10 | 定位具体失控程序 |
| 清理进程 | pkill -u oracle sendmail pkill -u oracle crond | 杀死指定用户的特定进程 |
| 查看 crontab | crontab -u oracle -l | 检查定时任务 |
| 固化配置 | 见上文第7步 | 永久生效 |
总结
故障根源是 oracle 用户的 cron 任务反复拉起 sendmail/crond 进程,导致 PID 耗尽。
通过临时调高 PID 上限、清理失控进程、修复定时任务并固化内核/用户限制,彻底解决了 SSH 连接拒绝和 fork 失败的问题。
完成后,SSH 连接恢复正常。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
