监控进程状态的脚本如何编写

wen 实用脚本 1

从零搭建高效的系统守护者

📖 目录导读

  1. 为什么需要监控进程状态?
  2. 进程监控的核心原理
  3. 手把手教你编写第一个监控脚本
  4. 进阶技巧:自动重启与日志记录
  5. 常见问题与解决方案(FAQ)
  6. 附录:脚本模板与最佳实践

为什么需要监控进程状态?

在服务器运维或日常开发中,进程意外崩溃、死锁或资源耗尽的情况时有发生,一个没有守护进程的Web服务可能在凌晨突然宕机,导致业务中断数小时。监控进程状态的核心目的是:第一时间发现异常并自动恢复,避免人工介入的延迟。

监控进程状态的脚本如何编写

根据监控实践统计,配置进程监控脚本后,系统可用性可从95%提升至99.9%以上,这意味着每月停机时间从36小时缩短至43分钟。


进程监控的核心原理

要编写有效的监控脚本,先理解操作系统如何管理进程:

1 进程状态的关键指标

  • 运行状态(R):进程正在执行
  • 睡眠状态(S):等待资源(如I/O、锁)
  • 僵尸状态(Z):进程已结束但父进程未回收资源
  • 停止状态(T):被信号暂停

2 监控本质:检查进程是否存在

脚本通过以下方式判断:

  • PID文件检查:通过存储进程PID的文件核对
  • 进程名匹配:使用pspgrep命令搜索进程列表
  • 端口检测:验证监听端口是否存活(适用于网络服务)

💡 SEO提示:使用时融入关键词“linux进程监控”“shell脚本检测进程”。


手把手教你编写第一个监控脚本

1 基础版一:检测进程是否存在

#!/bin/bash
# 定义要监控的进程名
PROCESS_NAME="nginx"
# 检查进程是否在运行
if ! pgrep -x "$PROCESS_NAME" > /dev/null; then
    echo "$(date) - 进程 $PROCESS_NAME 未运行,开始启动..."
    systemctl start nginx
else
    echo "$(date) - 进程 $PROCESS_NAME 运行正常"
fi

代码解释

  • pgrep -x:精确匹配进程名(不加-x会匹配包含该名称的子进程)
  • > /dev/null:丢弃标准输出,只保留退出状态码
  • systemctl start:自动重启(适用于systemd管理的服务)

2 基础版二:检查端口是否监听

适用于数据库、Web服务器等网络服务:

#!/bin/bash
PORT=3306  # MySQL默认端口
if netstat -tlnp | grep ":$PORT " > /dev/null; then
    echo "端口 $PORT 正常监听"
else
    echo "端口 $PORT 未监听,启动MySQL..."
    systemctl start mysqld
fi

3 加入资源监控(进阶)

#!/bin/bash
# 检查CPU使用率是否超过85%
CPU_THRESHOLD=85
PROCESS_NAME="java"
USAGE=$(ps -C "$PROCESS_NAME" -o %cpu --no-headers | awk '{sum+=$1} END {print sum}')
if (( $(echo "$USAGE > $CPU_THRESHOLD" | bc -l) )); then
    echo "警告:进程 $PROCESS_NAME CPU使用率达 ${USAGE}%"
    # 可选:发送告警邮件
else
    echo "CPU使用率正常"
fi

进阶技巧:自动重启与日志记录

1 带日志的完整脚本模板

#!/bin/bash
# 配置区
PROCESS_NAME="mysqld"
LOG_FILE="/var/log/process_monitor.log"
MAX_RESTART=3
RESTART_COUNT=0
# 日志函数
log() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
}
# 监控循环
while true; do
    if ! pgrep -x "$PROCESS_NAME" > /dev/null; then
        log "进程 $PROCESS_NAME 已停止,尝试重启..."
        systemctl start "$PROCESS_NAME"
        RESTART_COUNT=$((RESTART_COUNT + 1))
        if [ $RESTART_COUNT -ge $MAX_RESTART ]; then
            log "达到最大重启次数,发送紧急通知"
            # 这里可以集成邮件或Slack通知
            break
        fi
    else
        RESTART_COUNT=0  # 重置计数器
    fi
    sleep 10  # 每10秒检查一次
done

2 使用cron实现定时监控(代替死循环)

/etc/crontab中添加:

*/1 * * * * root /usr/local/bin/check_process.sh

每分钟执行一次监控脚本,避免while循环消耗资源。


常见问题与解决方案(FAQ)

Q1:如何监控非systemd管理的进程(如第三方软件)?

A:使用nohup启动进程时保存PID文件:

nohup ./myapp > /dev/null 2>&1 &
echo $! > /var/run/myapp.pid

监控脚本通过kill -0 $(cat /var/run/myapp.pid)检查进程存活。

Q2:脚本误判怎么办?比如进程名被其他程序占用?

A:采用“三重验证”策略:

  1. 检查进程名(ps aux | grep -w myapp
  2. 检查PID文件(kill -0 $PID
  3. 检查端口(netstat -tlnp | grep 8080

Q3:如何发送告警通知?

A:集成企业微信或邮件:

# 邮件通知
mail -s "进程告警" admin@example.com < alert.txt
# 企业微信机器人
curl -X POST -H "Content-Type: application/json" \
     -d '{"content":"进程 $PROCESS_NAME 异常"}' \
     https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_KEY

Q4:脚本本身崩溃怎么办?

A:使用supervisord管理监控脚本本身,实现“监视监控器”的双层守护架构。


附录:脚本最佳实践模板

生产环境推荐模板(Python版)

#!/usr/bin/env python3
import subprocess, time, os
def check_process(name):
    cmd = f"pgrep -x {name}"
    result = subprocess.run(cmd.split(), capture_output=True, text=True)
    return result.returncode == 0
def restart_service(service_name):
    subprocess.run(["systemctl", "restart", service_name])
def log_event(msg):
    with open("/var/log/monitor.log", "a") as f:
        f.write(f"{time.ctime()} - {msg}\n")
if __name__ == "__main__":
    process_name = "nginx"
    while True:
        if not check_process(process_name):
            log_event(f"进程 {process_name} 宕机,启动中...")
            restart_service(process_name)
        time.sleep(30)

关键参数优化建议

  • 检查频率:关键服务每10秒,常规服务每分钟
  • 重生次数限制:建议3次/5分钟内,防止死循环重启
  • 内存泄漏检测:额外监控RSS内存是否持续增长

编写监控脚本的核心在于:明确监控指标(进程、端口、资源)→ 简单可靠的检测逻辑 → 带限制的自动恢复机制,建议从pgrep+systemctl开始实验,逐步加入端口检查和资源告警,最后用cron或supervisord确保脚本本身高可用,通过本文的模板和FAQ,你已具备构建生产级监控系统的能力。

抱歉,评论功能暂时关闭!