下面是一个 Python 脚本,用于监控 PHP-FPM 进程的 CPU 使用率,并在超过阈值时自动杀死这些进程。
#!/usr/bin/env python3 import os import psutil import time import argparse from datetime import datetime def monitor_php_fpm(cpu_threshold, check_interval, max_duration): """ 监控 PHP-FPM 进程,杀死 CPU 使用率超过阈值的进程 参数: cpu_threshold (float): CPU 使用率阈值(百分比) check_interval (int): 检查间隔(秒) max_duration (int): 最大允许持续时间(秒) """ print(f"开始监控 PHP-FPM 进程,CPU 阈值: {cpu_threshold}%,检查间隔: {check_interval}秒") # 存储进程和其高CPU使用的开始时间 high_cpu_processes = {} while True: try: current_time = time.time() # 查找所有 PHP-FPM 进程 for proc in psutil.process_iter(['pid', 'name', 'cmdline', 'cpu_percent']): try: # 检查是否是 PHP-FPM 进程 if proc.info['name'] == 'php-fpm' or 'php-fpm' in ' '.join(proc.info['cmdline'] or []): cpu_percent = proc.cpu_percent(interval=0.1) if cpu_percent > cpu_threshold: pid = proc.info['pid'] if pid not in high_cpu_processes: high_cpu_processes[pid] = current_time print(f"[{datetime.now()}] 检测到高CPU进程 PID: {pid}, CPU: {cpu_percent}%") else: duration = current_time - high_cpu_processes[pid] if duration >= max_duration: # 杀死进程 proc.kill() print(f"[{datetime.now()}] 已杀死进程 PID: {pid}, 持续高CPU: {duration:.1f}秒, CPU: {cpu_percent}%") del high_cpu_processes[pid] else: # CPU 恢复正常,从监控中移除 if proc.info['pid'] in high_cpu_processes: del high_cpu_processes[proc.info['pid']] except (psutil.NoSuchProcess, psutil.AccessDenied): continue # 清理已经不存在的进程 for pid in list(high_cpu_processes.keys()): if not psutil.pid_exists(pid): del high_cpu_processes[pid] time.sleep(check_interval) except KeyboardInterrupt: print("\n监控已停止") break except Exception as e: print(f"发生错误: {e}") time.sleep(check_interval) if __name__ == "__main__": parser = argparse.ArgumentParser(description='监控 PHP-FPM 进程 CPU 使用率并自动杀死高占用进程') parser.add_argument('--threshold', type=float, default=90.0, help='CPU 使用率阈值(百分比)') parser.add_argument('--interval', type=int, default=5, help='检查间隔(秒)') parser.add_argument('--duration', type=int, default=30, help='最大允许持续时间(秒)') args = parser.parse_args() monitor_php_fpm(args.threshold, args.interval, args.duration)
使用说明
- 将上述脚本保存为
php_fpm_monitor.py
- 确保已安装 Python 3 和 psutil 库(可通过
pip install psutil
安装) - 运行脚本:
python3 php_fpm_monitor.py
可选参数
--threshold
: CPU 使用率阈值(默认90%)--interval
: 检查间隔时间(默认5秒)--duration
: 允许高CPU持续的最长时间(默认30秒)
示例:设置阈值为80%,检查间隔10秒,最大持续时间60秒
python3 php_fpm_monitor.py --threshold 80 --interval 10 --duration 60
注意事项
- 脚本需要以 root 权限运行才能杀死进程
- 建议先在测试环境中验证脚本行为
- 可以结合系统服务(如 systemd)将脚本设置为后台运行
- 频繁杀死 PHP-FPM 进程可能影响网站正常运行,建议先调查高CPU使用的原因
将Python脚本包装成systemctl服务
将Python脚本作为systemd服务运行可以让你的脚本在系统启动时自动运行,并且可以方便地管理(启动、停止、查看状态等)。以下是详细步骤:
1. 创建服务文件
在/etc/systemd/system/
目录下创建一个以.service
结尾的服务文件,例如:
vim /etc/systemd/system/php_fpm_monitor.service
2. 编写服务文件内容
[Unit] Description=PHP-FPM Monitor Service After=network.target [Service] User=root Group=root WorkingDirectory=/www/scripts ExecStart=/usr/bin/python3 /www/scripts/php_fpm_monitor.py Restart=always RestartSec=3 Environment=PYTHONUNBUFFERED=1 [Install] WantedBy=multi-user.target
参数说明:
- Description: 服务的描述
- User/Group: 运行脚本的用户和组
- WorkingDirectory: 脚本所在目录
- ExecStart: 启动命令(使用完整路径)
- Restart: 设置自动重启策略
- Environment: 设置环境变量(PYTHONUNBUFFERED=1确保日志实时输出)
3.重新加载systemd配置
systemctl daemon-reload
4.启用并启动服务
# 设置服务 systemctl enable php_fpm_monitor.service # 启动服务 systemctl start php_fpm_monitor.service
5.检查服务状态
systemctl status php_fpm_monitor.service
6. 常用命令
- 启动服务:
systemctl start php_fpm_monitor
- 停止服务:
systemctl stop php_fpm_monitor
- 重启服务:
systemctl restart php_fpm_monitor
- 查看日志:
journalctl -u php_fpm_monitor -f
高级配置建议
- 日志记录:考虑在Python脚本中使用logging模块,并将日志输出到特定文件
- 环境变量:可以使用
EnvironmentFile
指令加载包含环境变量的文件 - 资源限制:可以设置内存限制、CPU优先级等
- 依赖关系:使用
After
和Requires
指定服务依赖关系
示例完整服务文件
[Unit] Description=Web Scraping Service After=network.target postgresql.service [Service] User=scraper Group=scraper WorkingDirectory=/home/scraper/web_scraper EnvironmentFile=/home/scraper/web_scraper/.env ExecStart=/home/scraper/web_scraper/venv/bin/python /home/scraper/web_scraper/main.py Restart=on-failure RestartSec=30 StandardOutput=file:/var/log/web_scraper/out.log StandardError=file:/var/log/web_scraper/err.log [Install] WantedBy=multi-user.target