本文目录导读:

在PHP项目中实现告警回调自动触发修复脚本,通常有以下几个关键步骤和方案:
告警回调接收端设计
创建告警接收接口
// alert-webhook.php
<?php
header('Content-Type: application/json');
// 验证来源(安全校验)
$validTokens = ['your_secret_token_123'];
$receivedToken = $_SERVER['HTTP_X_ALERT_TOKEN'] ?? '';
if (!in_array($receivedToken, $validTokens)) {
http_response_code(403);
die(json_encode(['error' => 'Invalid token']));
}
// 解析告警数据
$rawData = file_get_contents('php://input');
$alertData = json_decode($rawData, true);
// 验证数据完整性
if (json_last_error() !== JSON_ERROR_NONE) {
http_response_code(400);
die(json_encode(['error' => 'Invalid JSON']));
}
// 处理告警
$result = handleAlert($alertData);
echo json_encode(['status' => 'success', 'result' => $result]);
function handleAlert($alertData) {
$alertType = $alertData['alert_type'] ?? '';
$severity = $alertData['severity'] ?? 'warning';
$message = $alertData['message'] ?? '';
// 记录告警日志
logAlert($alertType, $severity, $message);
// 判断是否需要自动修复
if (shouldAutoRepair($alertType, $severity)) {
return executeRepairScript($alertType, $alertData);
}
return ['action' => 'logged_only'];
}
function shouldAutoRepair($alertType, $severity) {
// 定义可自动修复的告警类型和级别
$autoRepairRules = [
'disk_full' => ['critical', 'warning'],
'high_cpu' => ['critical'],
'service_down' => ['critical', 'warning'],
'database_connection' => ['critical']
];
return isset($autoRepairRules[$alertType])
&& in_array($severity, $autoRepairRules[$alertType]);
}
执行修复脚本
安全执行脚本
function executeRepairScript($alertType, $alertData) {
$scriptMap = [
'disk_full' => '/opt/scripts/clean_disk.sh',
'high_cpu' => '/opt/scripts/restart_service.sh',
'service_down' => '/opt/scripts/restart_service.sh',
'database_connection' => '/opt/scripts/db_repair.sh'
];
if (!isset($scriptMap[$alertType])) {
return ['error' => 'No repair script configured for this alert type'];
}
$scriptPath = $scriptMap[$alertType];
// 安全检查:脚本必须存在且可执行
if (!file_exists($scriptPath) || !is_executable($scriptPath)) {
logError("Repair script not found or not executable: $scriptPath");
return ['error' => 'Script not available'];
}
// 构建命令,传递参数
$command = escapeshellcmd($scriptPath) . ' ' .
escapeshellarg($alertType) . ' ' .
escapeshellarg(json_encode($alertData));
// 使用proc_open来更好地控制执行
$descriptorspec = [
0 => ["pipe", "r"], // stdin
1 => ["pipe", "w"], // stdout
2 => ["pipe", "w"] // stderr
];
$process = proc_open($command, $descriptorspec, $pipes);
if (is_resource($process)) {
fclose($pipes[0]); // 关闭stdin
$output = stream_get_contents($pipes[1]);
$errorOutput = stream_get_contents($pipes[2]);
fclose($pipes[1]);
fclose($pipes[2]);
$returnCode = proc_close($process);
// 记录执行结果
logRepairResult($alertType, $returnCode, $output, $errorOutput);
return [
'success' => $returnCode === 0,
'return_code' => $returnCode,
'output' => $output,
'error' => $errorOutput
];
}
return ['error' => 'Failed to execute script'];
}
修复脚本示例
Shell脚本示例
#!/bin/bash
# /opt/scripts/clean_disk.sh
ALERT_TYPE=$1
ALERT_DATA=$2
# 解析告警数据中的磁盘信息
DISK_PATH=$(echo $ALERT_DATA | python3 -c "import sys,json; print(json.load(sys.stdin).get('disk_path', '/'))" 2>/dev/null)
# 清理策略
case $DISK_PATH in
"/tmp")
find /tmp -type f -atime +7 -delete
;;
"/var/log")
find /var/log -name "*.log.*" -mtime +30 -delete
journalctl --vacuum-time=7d
;;
"/")
apt-get clean
docker system prune -f --volumes
;;
*)
# 通用清理
find $DISK_PATH -type f -size +100M -atime +30 -delete 2>/dev/null
;;
esac
# 报告清理结果
df -h $DISK_PATH | tail -1
exit $?
防止重复执行和限流
// 使用文件锁防止重复执行
function acquireRepairLock($alertType) {
$lockFile = "/tmp/repair_lock_{$alertType}.lock";
$fp = fopen($lockFile, 'c');
if (!flock($fp, LOCK_EX | LOCK_NB)) {
return false; // 已经有进程在执行
}
// 设置锁的超时时间(例如5分钟)
$lockData = ['pid' => getmypid(), 'time' => time()];
fwrite($fp, json_encode($lockData));
fflush($fp);
return $fp;
}
function releaseRepairLock($fp) {
flock($fp, LOCK_UN);
fclose($fp);
}
// 在handleAlert中使用
$lock = acquireRepairLock($alertType);
if ($lock === false) {
return ['action' => 'skipped', 'reason' => 'Repair already in progress'];
}
try {
$result = executeRepairScript($alertType, $alertData);
releaseRepairLock($lock);
return $result;
} catch (Exception $e) {
releaseRepairLock($lock);
throw $e;
}
告警平台配置示例
Prometheus Alertmanager配置
# alertmanager.yml
receivers:
- name: 'php-auto-repair'
webhook_configs:
- url: 'https://your-server.com/alert-webhook.php'
send_resolved: false
http_config:
headers:
X-Alert-Token: 'your_secret_token_123'
Zabbix配置
// Zabbix告警脚本
<?php
// /usr/lib/zabbix/alertscripts/php_remediation.php
$webhookUrl = 'https://your-server.com/alert-webhook.php';
$alertData = [
'alert_type' => $argv[1],
'severity' => $argv[2],
'message' => $argv[3],
'host' => $argv[4],
'timestamp' => time()
];
$ch = curl_init($webhookUrl);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($alertData));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'X-Alert-Token: your_secret_token_123'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
curl_close($ch);
安全注意事项
- 命令注入防护:使用
escapeshellcmd和escapeshellarg - 权限控制:Web服务器用户应有最小权限
- 执行时间限制:设置超时机制
function executeScriptWithTimeout($command, $timeout = 30) {
$process = proc_open($command, $descriptorspec, $pipes);
// 设置非阻塞模式
stream_set_blocking($pipes[1], false);
stream_set_blocking($pipes[2], false);
$startTime = time();
$output = '';
$errorOutput = '';
while (true) {
// 检查是否超时
if (time() - $startTime > $timeout) {
proc_terminate($process, 9); // SIGKILL
return ['error' => 'Execution timeout'];
}
$status = proc_get_status($process);
if (!$status['running']) {
break;
}
// 读取输出
$output .= stream_get_contents($pipes[1]);
$errorOutput .= stream_get_contents($pipes[2]);
usleep(100000); // 100ms sleep
}
// 读取剩余输出
$output .= stream_get_contents($pipes[1]);
$errorOutput .= stream_get_contents($pipes[2]);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
$returnCode = proc_close($process);
return [
'output' => $output,
'error' => $errorOutput,
'return_code' => $returnCode
];
}
这个方案提供了一个安全、可扩展的告警自动修复框架,根据具体需求,可以调整修复规则、添加更多告警类型,或集成到现有的告警系统中。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播