本文目录导读:

我来给你写几个不同场景的PHP看门狗脚本示例:
基础版 - 定时检查进程是否运行
<?php
/**
* 基础看门狗脚本 - 检查指定进程是否运行
* 运行方式:php watchdog.php
*/
class Watchdog {
private $processName;
private $restartCommand;
private $checkInterval = 60; // 检查间隔(秒)
private $logFile;
public function __construct($processName, $restartCommand, $logFile = 'watchdog.log') {
$this->processName = $processName;
$this->restartCommand = $restartCommand;
$this->logFile = $logFile;
}
// 检查进程是否运行
private function isProcessRunning() {
// Linux/Mac 系统
if (PHP_OS_FAMILY === 'Linux' || PHP_OS_FAMILY === 'Darwin') {
exec("pgrep -f '{$this->processName}'", $output);
return !empty($output);
}
// Windows 系统
else {
exec("tasklist | findstr /i \"{$this->processName}\"", $output);
return !empty($output);
}
}
// 重启进程
private function restartProcess() {
$this->log("进程 {$this->processName} 未运行,正在重启...");
// 后台执行重启命令
if (PHP_OS_FAMILY === 'Linux' || PHP_OS_FAMILY === 'Darwin') {
exec($this->restartCommand . " > /dev/null 2>&1 &");
} else {
exec("start /B " . $this->restartCommand);
}
$this->log("重启命令已执行");
}
// 记录日志
private function log($message) {
$time = date('Y-m-d H:i:s');
file_put_contents($this->logFile, "[{$time}] {$message}\n", FILE_APPEND);
echo "[{$time}] {$message}\n";
}
// 启动看门狗
public function run() {
$this->log("看门狗启动,监控进程: {$this->processName}");
while (true) {
if (!$this->isProcessRunning()) {
$this->restartProcess();
} else {
$this->log("进程 {$this->processName} 正常运行中");
}
sleep($this->checkInterval);
}
}
}
// 使用示例
$watchdog = new Watchdog(
'my_worker.php', // 要监控的进程名
'php /path/to/my_worker.php', // 重启命令
'/var/log/watchdog.log' // 日志文件
);
$watchdog->run();
进阶版 - 支持多进程和健康检查
<?php
/**
* 进阶版看门狗 - 支持多进程监控和HTTP健康检查
* 运行方式:php watchdog_advanced.php
*/
class AdvancedWatchdog {
private $services = [];
private $checkInterval = 30;
private $logFile = 'watchdog.log';
private $maxMemoryUsage = 104857600; // 100MB
public function __construct($logFile = 'watchdog.log') {
$this->logFile = $logFile;
}
// 添加要监控的服务
public function addService($name, $config) {
$this->services[$name] = array_merge([
'command' => '',
'process_name' => '',
'health_check_url' => null,
'restart_command' => null,
'max_restarts' => 5, // 最大重启次数
'restart_count' => 0,
'last_restart_time' => 0,
'min_restart_interval' => 60 // 最小重启间隔(秒)
], $config);
}
// 检查进程状态
private function checkProcessStatus($service) {
$processName = $service['process_name'];
if (PHP_OS_FAMILY === 'Linux' || PHP_OS_FAMILY === 'Darwin') {
exec("pgrep -f '{$processName}'", $pids);
return !empty($pids);
} else {
exec("tasklist | findstr /i \"{$processName}\"", $output);
return !empty($output);
}
}
// HTTP健康检查
private function healthCheckUrl($url) {
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_CONNECTTIMEOUT => 5
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// 检查响应
if ($httpCode != 200) {
return false;
}
// 如果需要,可以检查响应内容
// return strpos($response, 'OK') !== false;
return true;
}
// 检查内存使用
private function checkMemoryUsage($processName) {
if (PHP_OS_FAMILY !== 'Linux') {
return true; // 非Linux系统跳过内存检查
}
exec("ps aux | grep '{$processName}' | grep -v grep", $output);
foreach ($output as $line) {
// 解析内存使用(RSS列)
$parts = preg_split('/\s+/', $line);
if (isset($parts[5])) {
$memoryKB = (int)$parts[5];
if ($memoryKB * 1024 > $this->maxMemoryUsage) {
return false;
}
}
}
return true;
}
// 重启服务
private function restartService($name, $service) {
$now = time();
// 检查重启次数限制
if ($service['restart_count'] >= $service['max_restarts']) {
$this->log("服务 {$name} 已达到最大重启次数,发送告警", 'ERROR');
$this->sendAlert("服务 {$name} 连续失败,需要人工介入");
return;
}
// 检查重启间隔
if (($now - $service['last_restart_time']) < $service['min_restart_interval']) {
$this->log("服务 {$name} 重启过于频繁,跳过此次重启", 'WARNING');
return;
}
$this->log("重启服务: {$name}", 'INFO');
// 执行重启命令
$restartCommand = $service['restart_command'] ?? $service['command'];
if (PHP_OS_FAMILY === 'Linux' || PHP_OS_FAMILY === 'Darwin') {
exec($restartCommand . " > /dev/null 2>&1 &");
} else {
exec("start /B " . $restartCommand);
}
// 更新状态
$service['restart_count']++;
$service['last_restart_time'] = $now;
$this->services[$name] = $service;
$this->log("服务 {$name} 已重启 ({$service['restart_count']}/{$service['max_restarts']})", 'INFO');
}
// 发送告警
private function sendAlert($message) {
// 这里可以集成短信、邮件、微信等告警
// 示例:发送邮件
// mail('admin@example.com', 'Watchdog Alert', $message);
// 或者写日志
$this->log("告警: {$message}", 'CRITICAL');
}
// 记录日志
private function log($message, $level = 'INFO') {
$time = date('Y-m-d H:i:s');
$logMessage = "[{$time}] [{$level}] {$message}\n";
file_put_contents($this->logFile, $logMessage, FILE_APPEND);
echo $logMessage;
}
// 运行看门狗
public function run() {
$this->log("高级看门狗启动,监控 " . count($this->services) . " 个服务");
while (true) {
foreach ($this->services as $name => $service) {
$this->checkService($name, $service);
}
sleep($this->checkInterval);
}
}
// 检查单个服务
private function checkService($name, $service) {
// 1. 检查进程是否存在
if (!$this->checkProcessStatus($service)) {
$this->log("服务 {$name} 进程不存在", 'WARNING');
$this->restartService($name, $service);
return;
}
// 2. 健康检查(可选)
if ($service['health_check_url']) {
if (!$this->healthCheckUrl($service['health_check_url'])) {
$this->log("服务 {$name} HTTP健康检查失败", 'WARNING');
$this->restartService($name, $service);
return;
}
}
// 3. 内存检查
if (!$this->checkMemoryUsage($service['process_name'])) {
$this->log("服务 {$name} 内存使用过高", 'WARNING');
$this->restartService($name, $service);
return;
}
$this->log("服务 {$name} 运行正常", 'INFO');
}
}
// 使用示例
$watchdog = new AdvancedWatchdog('/var/log/advanced_watchdog.log');
// 添加Web服务监控
$watchdog->addService('webapp', [
'command' => 'php -S 0.0.0.0:8080',
'process_name' => 'php -S',
'health_check_url' => 'http://localhost:8080/health',
'restart_command' => 'nohup php -S 0.0.0.0:8080 &',
'max_restarts' => 10,
'min_restart_interval' => 120
]);
// 添加队列处理器监控
$watchdog->addService('worker', [
'command' => 'php worker.php',
'process_name' => 'worker.php',
'restart_command' => 'nohup php /path/to/worker.php &',
'max_restarts' => 20
]);
$watchdog->run();
守护进程版 - 作为系统服务运行
<?php
/**
* 守护进程版看门狗 - 通过daemonize实现后台运行
* 运行方式:php watchdog_daemon.php start|stop|status
*/
class DaemonWatchdog {
private $pidFile;
private $logFile;
private $daemonName = 'watchdog';
public function __construct($pidFile = '/tmp/watchdog.pid', $logFile = '/tmp/watchdog.log') {
$this->pidFile = $pidFile;
$this->logFile = $logFile;
}
// 守护进程化
private function daemonize() {
// 创建子进程
$pid = pcntl_fork();
if ($pid == -1) {
die("无法创建子进程\n");
} elseif ($pid > 0) {
// 父进程退出
exit(0);
}
// 子进程继续执行
posix_setsid(); // 创建新的会话
// 第二次fork,防止获取终端
$pid = pcntl_fork();
if ($pid == -1) {
die("第二次fork失败\n");
} elseif ($pid > 0) {
exit(0);
}
// 保存进程号
file_put_contents($this->pidFile, posix_getpid());
// 重定向标准输入输出
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);
$stdin = fopen('/dev/null', 'r');
$stdout = fopen($this->logFile, 'ab');
$stderr = fopen($this->logFile, 'ab');
return true;
}
// 启动守护进程
public function start() {
if ($this->isRunning()) {
echo "看门狗已经在运行 (PID: " . $this->getPid() . ")\n";
return;
}
echo "启动看门狗守护进程...\n";
$this->daemonize();
// 这里写看门狗的主要逻辑
$this->mainLoop();
}
// 停止守护进程
public function stop() {
if (!$this->isRunning()) {
echo "看门狗没有在运行\n";
return;
}
$pid = $this->getPid();
echo "停止看门狗 (PID: {$pid})...\n";
posix_kill($pid, SIGTERM);
// 等待进程退出
usleep(500000);
if (file_exists($this->pidFile)) {
unlink($this->pidFile);
}
echo "看门狗已停止\n";
}
// 查看状态
public function status() {
if ($this->isRunning()) {
echo "看门狗状态: 运行中 (PID: " . $this->getPid() . ")\n";
} else {
echo "看门狗状态: 未运行\n";
}
}
// 检查是否在运行
private function isRunning() {
if (!file_exists($this->pidFile)) {
return false;
}
$pid = $this->getPid();
return posix_kill($pid, 0); // 发送信号0检查进程是否存在
}
// 获取进程ID
private function getPid() {
return (int)file_get_contents($this->pidFile);
}
// 主循环
private function mainLoop() {
$this->logMessage("看门狗守护进程启动");
// 在这里实现具体的监控逻辑
while (true) {
// 监控逻辑
$this->monitorProcesses();
// 每隔60秒检查一次
sleep(60);
}
}
// 监控进程
private function monitorProcesses() {
// 检查关键进程
$processes = [
'mysql' => 'service mysql start',
'nginx' => 'service nginx start',
'php-fpm' => 'service php-fpm start'
];
foreach ($processes as $process => $restartCommand) {
exec("pgrep -f '{$process}'", $output);
if (empty($output)) {
$this->logMessage("{$process} 未运行,执行重启");
exec($restartCommand);
}
}
}
// 记录日志
private function logMessage($message) {
$time = date('Y-m-d H:i:s');
file_put_contents($this->logFile, "[{$time}] {$message}\n", FILE_APPEND);
}
// 命令行接口
public function commandLine() {
global $argv;
if (!isset($argv[1])) {
echo "使用方法: php watchdog_daemon.php {start|stop|status}\n";
exit(1);
}
switch ($argv[1]) {
case 'start':
$this->start();
break;
case 'stop':
$this->stop();
break;
case 'status':
$this->status();
break;
default:
echo "无效的命令: {$argv[1]}\n";
echo "使用方法: php watchdog_daemon.php {start|stop|status}\n";
exit(1);
}
}
}
// 使用
$daemon = new DaemonWatchdog();
$daemon->commandLine();
使用Systemd托管(Linux推荐)
创建一个systemd服务文件:
# /etc/systemd/system/watchdog.service [Unit] Description=PHP Watchdog Service After=network.target [Service] Type=simple User=www-data WorkingDirectory=/var/www ExecStart=/usr/bin/php /path/to/watchdog.php Restart=always RestartSec=60 StartLimitInterval=300 StartLimitBurst=5 EnvironmentFile=/etc/watchdog.env [Install] WantedBy=multi-user.target
使用systemd命令:
# 启动服务 sudo systemctl start watchdog # 设置开机启动 sudo systemctl enable watchdog # 查看状态 sudo systemctl status watchdog # 查看日志 journalctl -u watchdog -f
使用建议
- 配置文件化:将监控的服务信息放入配置文件(JSON/YAML)
- 增加通知机制:集成邮件、短信、企业微信等告警
- 合并到crontab:如果没有daemon环境,可以用crontab定期执行
- 增加状态持久化:重启后保留统计信息
- 完善日志记录:记录所有操作和异常
需要根据具体的使用场景选择合适的方案。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播