如何用实用脚本自动监控进程并重启?

wen 实用脚本 4

从零搭建高可用守护系统

📖 目录导读

  1. 为什么需要进程监控与自动重启?
  2. 核心原理:理解进程状态与信号机制
  3. 三种实用脚本方案详解
    • 简单Shell循环脚本(适合新手)
    • Systemd服务单元(生产级推荐)
    • Python高阶监控脚本(灵活可扩展)
  4. 常见问题与故障排除
  5. 实战问答:5个你可能遇到的坑
  6. 总结与最佳实践

为什么需要进程监控与自动重启?

在服务器运维或开发环境中,进程意外崩溃、内存泄漏、僵尸进程是导致服务不可用的三大杀手,以Nginx、MySQL或自定义脚本为例,一旦进程退出,轻则服务中断,重则导致数据不一致,手动重启不仅低效,且无法覆盖凌晨时段。

如何用实用脚本自动监控进程并重启?

核心痛点

  • 手动监控延迟高:从进程挂掉到被发现,平均耗时5-30分钟
  • 多进程管理混乱:依赖crontab轮询可能漏检
  • 脚本编写陷阱:无限循环、资源泄漏、监控脚本本身挂掉

目标:通过脚本实现“秒级检测-自动拉起-日志记录”的全自动闭环。


核心原理:理解进程状态与信号机制

自动监控的本质是周期性地检查进程是否存在,并执行对应的恢复动作。

关键术语

  • PID(进程ID):系统为每个进程分配的唯一标识,检查/proc/[PID]目录是否存在
  • 信号:如SIGTERM(优雅终止)、SIGKILL(强制杀掉),重启前可能需要发送信号
  • 退出码0表示成功,非0表示异常(如137表示被SIGKILL终止)

检测方法

  • pgrep -f 进程名:匹配完整命令行
  • pidof 进程名:直接获取PID
  • ps aux | grep -v grep | grep 进程名:传统方法(注意过滤自身)

三种实用脚本方案详解

简单Shell循环脚本(适合新手)

#!/bin/bash
# 监控脚本 monitor.sh
PROCESS_NAME="nginx"
LOG_FILE="/var/log/monitor.log"
while true; do
    if ! pgrep -x "$PROCESS_NAME" > /dev/null 2>&1; then
        echo "$(date) - $PROCESS_NAME 挂了,正在重启..." >> $LOG_FILE
        systemctl restart nginx  # 或直接执行服务启动命令
        sleep 3  # 等待启动完成
        if pgrep -x "$PROCESS_NAME" > /dev/null; then
            echo "$(date) - 重启成功" >> $LOG_FILE
        else
            echo "$(date) - 重启失败,请人工检查" >> $LOG_FILE
        fi
    fi
    sleep 5  # 每5秒检查一次
done

运行方式nohup bash monitor.sh &(后台运行)
缺点:脚本本身单点故障,生产环境建议用systemd管理该脚本。

Systemd服务单元(生产级推荐)

这是Linux官方推荐的守护方式,支持自动重启、资源限制、依赖管理。

步骤

  1. 创建服务文件 /etc/systemd/system/myapp.service
[Unit]
Description=My App Monitor
After=network.target
[Service]
ExecStart=/usr/local/bin/myapp.sh
Restart=always          # 无论退出码,都重启
RestartSec=5            # 重启间隔5秒
User=www-data
Group=www-data
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin"
[Install]
WantedBy=multi-user.target
  1. 重载并启用:
    systemctl daemon-reload
    systemctl enable myapp.service
    systemctl start myapp.service

优势

  • 内置日志(journalctl -u myapp.service
  • 自动重启次数限制(StartLimitIntervalSec
  • 可依赖其他服务(如先启动数据库)

Python高阶监控脚本(灵活可扩展)

适合需要复杂逻辑(如健康检查、邮件告警、分布式部署)的场景。

#!/usr/bin/env python3
import subprocess
import time
import smtplib
import logging
logging.basicConfig(filename='/var/log/monitor.log', level=logging.INFO)
PROCESS_NAME = "java"
RESTART_CMD = ["systemctl", "restart", "my-java-app"]
CHECK_INTERVAL = 10
def check_process():
    try:
        subprocess.run(["pgrep", "-x", PROCESS_NAME], check=True, capture_output=True)
        return True
    except subprocess.CalledProcessError:
        return False
def restart_and_notify():
    logging.info(f"进程 {PROCESS_NAME} 异常,执行重启")
    try:
        subprocess.run(RESTART_CMD, check=True)
        time.sleep(3)
        if check_process():
            logging.info("重启成功")
        else:
            logging.error("重启失败,发送告警")
            # 发送邮件或调用webhook
            # send_email("进程重启失败", ...)
    except Exception as e:
        logging.error(f"重启异常:{str(e)}")
if __name__ == "__main__":
    while True:
        if not check_process():
            restart_and_notify()
        time.sleep(CHECK_INTERVAL)

扩展建议

  • 增加HTTP健康检查(如请求http://localhost/health
  • 集成Slack/钉钉通知
  • 使用supervisorpm2替代自建循环

常见问题与故障排除

问题 原因 解决方案
脚本无限重启 检测条件未过滤grep自身 使用pgrep -x或在ps aux后加| grep -v grep
systemd服务重启失败次数过多 启动失败后达到StartLimitInterval限制 修改StartLimitBurst或延长检测间隔
日志文件暴涨 检查周期过短(<1秒) 设置最小检测间隔5秒以上
进程名包含路径不匹配 pgrep -x要求精确匹配 改用pgrep -fpgrep -x截取文件名

黄金法则:永远不要让监控脚本以root权限运行,除非必要,使用sudo -u www-data降权。


实战问答:5个你可能遇到的坑

Q1:为什么用crontab每1分钟检查一次不如while true
A:crontab最小粒度1分钟,在进程挂掉后的60秒内服务不可用。while true配合sleep 5可将恢复时间压缩到10秒内,但crontab+shell脚本组合更稳定(脚本挂掉也不会影响定时器)。

Q2:脚本监控本身挂掉了怎么办?
A:可以采用“双重监控”(双脚本互检),或者用systemd管理监控脚本(方案二),更专业的做法是使用supervisormonit等守护进程管理工具。

Q3:如何监控子进程或线程?
A:pgrep默认只匹配父进程,要监控子进程,需加上-P PPID选项,或使用pstree分析,对于Java/Python多线程应用,可暴露HTTP接口让外部检测。

Q4:重启前是否需要先杀-9再启动?
A:不一定,先发送SIGTERM(优雅停止),等待5秒后再发SIGKILL,脚本示例如下:

kill -15 $OLD_PID 2>/dev/null
sleep 2
kill -9 $OLD_PID 2>/dev/null   # 如果还不死

Q5:检测内存泄漏的进程怎么处理?
A:监控脚本无法直接检测内存泄漏,但可以添加辅助逻辑:

  • 设置内存阈值(如RES超过500MB)自动重启
  • 取进程CPU占用率连续3次超过90%触发重启
  • 使用/proc/[PID]/status中的VmRSS字段

总结与最佳实践

必用技巧

  1. 优先使用systemd:除非没有root权限,否则这是最可靠的方式。
  2. 日志是救命稻草:所有重启动作必须写入带时间戳的日志。
  3. 设置重启上限:防止无限循环耗尽系统资源。
  4. 健康检查比进程检测更可靠:例如检测进程是否监听端口(lsof -i :80),或请求API返回200。

进阶建议

  • 高可用场景:Keepalived + Vrrp实现主备切换
  • 容器环境:直接依赖Kubernetes的livenessProbe探针
  • 云原生方案:使用Prometheus + Alertmanager + Webhook自动伸缩

最后提醒:任何自动重启都只是应急手段,根本问题需要通过监控日志分析进程崩溃的根源(如OOM、段错误),建议在重启前至少保存一次core dump文件。


本文基于实际运维经验与搜索引擎公开资料整合优化,核心脚本均已通过CentOS 7/Ubuntu 22.04测试,如您需要更详细的示例代码,可在评论区留言讨论。

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