Shell脚本如何监控进程数量(实战指南)
目录导读
为什么需要监控进程数量?
在生产服务器或开发环境中,进程数量异常往往是系统问题的“晴雨表”,举个真实案例:某电商网站业务高峰期,由于PHP-FPM子进程不断膨胀,导致服务器内存耗尽,最终引发502错误,通过进程数量监控脚本,运维人员可以在进程数超过阈值时自动触发告警,从而避免服务宕机。

典型场景包括:
- 防止僵尸进程堆积导致系统资源耗尽
- 监控Web服务器(如Nginx、Apache)的worker进程数量,确保负载均衡正常
- 检测恶意进程或脚本的异常行为
- 为Docker容器或微服务提供进程健康检查
核心监控原理与常用命令
1 关键命令解析
# 最核心三剑客 ps -ef | grep "进程名" | grep -v grep | wc -l pgrep -c "进程名" # 更精确的统计方式 top -bn1 | grep "Tasks" # 查看系统总进程数
ps命令的陷阱:直接使用ps aux | grep xxx会包含grep自身进程,务必加| grep -v grep过滤。
2 常用指标阈值
| 监控对象 | 常见告警阈值 | 说明 |
|---|---|---|
| 总进程数 | > 1000(视硬件配置) | 系统可创建进程数上限 |
| 单个服务进程 | 如PHP-FPM > 500 | 根据worker池配置设定 |
| 僵尸进程 | > 0 | 应始终保持为0 |
| 子进程增长速率 | 每分钟增长>20% | 可能有内存泄漏 |
实战:编写进程数量监控脚本
1 基础脚本框架
#!/bin/bash
# 功能:监控指定进程数量,超阈值则告警
PROCESS_NAME="nginx" # 替换为实际进程名(支持正则)
PROCESS_THRESHOLD=200 # 进程数阈值
SCRIPT_NAME="进程监控脚本"
# 获取进程数量
process_count=$(pgrep -c "$PROCESS_NAME" 2>/dev/null || echo 0)
# 判断是否超限
if [ "$process_count" -gt "$PROCESS_THRESHOLD" ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 警告:$PROCESS_NAME 当前进程数 $process_count,超过阈值 $PROCESS_THRESHOLD"
# 此处可插入告警动作(见第四部分)
else
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $PROCESS_NAME 进程数正常:$process_count"
fi
2 增强版:多进程监控
#!/bin/bash
declare -A PROC_MAP
PROC_MAP["nginx"]=200
PROC_MAP["php-fpm"]=300
PROC_MAP["mysqld"]=50
for proc in "${!PROC_MAP[@]}"; do
threshold=${PROC_MAP[$proc]}
count=$(pgrep -c "$proc")
echo "$proc 当前进程数: $count / 阈值: $threshold"
done
3 定时执行(crontab)
# 每5分钟执行一次 */5 * * * * /usr/local/bin/process_monitor.sh >> /var/log/process_monitor.log 2>&1
进阶:告警通知与日志记录
1 集成企业微信/Slack通知
# 企业微信机器人通知函数
send_wechat_notification() {
local message=$1
local webhook_url="https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_KEY"
curl -X POST -H "Content-Type: application/json" \
-d "{\"msgtype\":\"text\",\"text\":{\"content\":\"$message\"}}" \
"$webhook_url"
}
# 在告警逻辑中调用
if [ "$process_count" -gt "$PROCESS_THRESHOLD" ]; then
send_wechat_notification "服务器进程告警:$PROCESS_NAME 当前数量 $process_count"
fi
2 健康日志自动轮转
log_file="/var/log/process_monitor.log"
[ ! -f "$log_file" ] && touch "$log_file"
# 日志大小限制(10MB自动切割)
if [ $(stat -c%s "$log_file") -gt 10485760 ]; then
mv "$log_file" "${log_file}.$(date +%Y%m%d%H%M%S)"
touch "$log_file"
fi
问答专区
Q1:为什么我的ps命令统计结果比预期多1个进程?
A:经典陷阱!ps aux | grep nginx会包含当前grep命令自身的进程行,解决方案:使用grep -v grep过滤,或者直接用pgrep -c nginx更准确。
Q2:监控脚本在容器内执行需要注意什么?
A:容器内进程空间隔离,ps命令可能无法看到宿主机进程,建议:
- 在宿主机层面部署监控脚本
- 容器内使用
/proc文件系统直接读取/proc/1/status判断init进程健康状态 - 对于Docker,可设置
--restart=always策略
Q3:如何监控所有进程的总数?
total_procs=$(ps -e --no-headers | wc -l) # 或使用/proc更高效 total_procs=$(ls -d /proc/[0-9]* 2>/dev/null | wc -l)
Q4:脚本执行后没有任何输出,可能是什么问题?
- 检查脚本是否有执行权限:
chmod +x script.sh - 测试
pgrep命令本身是否能正确匹配进程名 - 确认crontab环境变量(PATH问题需使用绝对路径)
- 查看日志文件是否有写入权限
Q5:是否有更专业的进程监控工具? A:对于复杂监控场景,可组合工具:
- Prometheus + node_exporter(集成进程数指标)
- Monit(轻量级进程监控,支持自动恢复)
- Sysdig(Capture进程行为) 但Shell脚本的优势在于:零依赖、底层可见性强、适合快速部署验证。
后记:进程监控脚本是运维工具箱里的“瑞士军刀”,它不需要复杂的架构,却能解决核心的异常检测问题,建议运维人员将本文的脚本实践为模板,根据自身业务特性(如微服务进程名、容器编排)进行个性化定制,真正实现“故障未至,监控先行”。(文末附赠“三招测试小技巧”:1. 手动kill子进程测试阈值触发;2. 插入假进程测试正则匹配;3. 拔网线测试告警渠道可用性。)