You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

290 lines
12 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
require_once __DIR__ . '/../config/database.php';
require_once __DIR__ . '/../src/storage/Database.php';
require_once __DIR__ . '/../src/storage/ServiceRepository.php';
require_once __DIR__ . '/../src/storage/SystemSettingsRepository.php';
//
error_reporting(E_ALL);
ini_set('display_errors', 1);
session_start();
// 身份验证
if (!isset($_SESSION['user_id'])) {
header('Location: index.php');
exit;
}
$serviceRepo = new ServiceRepository();
$settingsRepo = new SystemSettingsRepository();
$message = '';
$error = '';
// ===================== 修改部分开始 =====================
// 添加服务控制函数
function startService($serviceName, $port) {
$scriptPath = __DIR__ . "/../scripts/start_{$serviceName}.php";
$logFile = __DIR__ . "/../logs/{$serviceName}.log";
// 检查服务是否已经在运行
if (isServiceRunning($serviceName)) {
return ['success' => false, 'message' => '服务已在运行'];
}
// 启动服务(后台运行)
$cmd = "php {$scriptPath} > {$logFile} 2>&1 & echo $!";
$pid = trim(shell_exec($cmd));
sleep(2); // 等待服务启动
if (isServiceRunning($serviceName)) {
return ['success' => true, 'pid' => $pid];
} else {
return ['success' => false, 'message' => '启动失败'];
}
}
function stopService($serviceName, $pid) {
if ($pid) {
// 使用 kill 命令终止进程
@exec("kill {$pid} 2>/dev/null");
sleep(1);
// 如果进程还在,强制终止
if (isServiceRunning($serviceName)) {
@exec("kill -9 {$pid} 2>/dev/null");
sleep(1);
}
} else {
// 如果没有PID查找并终止所有相关进程
@exec("pkill -f 'start_{$serviceName}.php' 2>/dev/null");
@exec("pkill -f 'SmtpServer.php' 2>/dev/null");
@exec("pkill -f 'Pop3Server.php' 2>/dev/null");
}
return !isServiceRunning($serviceName);
}
function isServiceRunning($serviceName) {
// 检查端口是否被监听
$port = ($serviceName === 'smtp') ? 25 : 110;
$cmd = "netstat -tlnp 2>/dev/null | grep :{$port} | grep LISTEN";
$result = shell_exec($cmd);
return !empty($result);
}
function getServicePid($serviceName) {
$port = ($serviceName === 'smtp') ? 25 : 110;
$cmd = "lsof -ti:{$port} 2>/dev/null | head -1";
return trim(shell_exec($cmd));
}
// ===================== 修改部分结束 =====================
// 处理服务起停
if (isset($_GET['action'])) {
$serviceName = $_GET['service'] ?? '';
$action = $_GET['action'] ?? '';
if ($serviceName === 'smtp' || $serviceName === 'pop3') {
// ===================== 修改部分开始 =====================
// 实际启动服务
$port = ($serviceName === 'smtp') ?
$settingsRepo->get('smtp_port', 25) :
$settingsRepo->get('pop3_port', 110);
$result = startService($serviceName, $port);
if ($result['success']) {
$pid = $result['pid'];
$serviceRepo->updateStatus($serviceName, true, $pid);
$message = strtoupper($serviceName) . "服务已启动 (PID: {$pid})";
} else {
$error = strtoupper($serviceName) . "服务启动失败: " . $result['message'];
}
// ===================== 修改部分结束 =====================
}
elseif ($action === 'stop') {
// ===================== 修改部分开始 =====================
// 实际停止服务
$status = $serviceRepo->getStatus($serviceName);
$pid = $status['pid'] ?? getServicePid($serviceName);
if (stopService($serviceName, $pid)) {
$serviceRepo->updateStatus($serviceName, false, null);
$message = strtoupper($serviceName) . "服务已停止";
} else {
$error = strtoupper($serviceName) . "服务停止失败";
}
// ===================== 修改部分结束 =====================
}
}
// 获取服务状态
$smtpStatus = $serviceRepo->getStatus('smtp');
$pop3Status = $serviceRepo->getStatus('pop3');
// 实际检查服务是否运行
$smtpRunning = isServiceRunning('smtp');
$pop3Running = isServiceRunning('pop3');
// 如果数据库状态与实际状态不一致,更新数据库
if ($smtpStatus['is_running'] != $smtpRunning) {
$pid = $smtpRunning ? getServicePid('smtp') : null;
$serviceRepo->updateStatus('smtp', $smtpRunning, $pid);
}
if ($pop3Status['is_running'] != $pop3Running) {
$pid = $pop3Running ? getServicePid('pop3') : null;
$serviceRepo->updateStatus('pop3', $pop3Running, $pid);
}
// 重新获取更新后的状态
$smtpStatus = $serviceRepo->getStatus('smtp');
$pop3Status = $serviceRepo->getStatus('pop3');
$smtpRunning = $smtpStatus['is_running'];
$pop3Running = $pop3Status['is_running'];
// ===================== 修改部分结束 =====================
// 获取端口设置
$smtpPort = $settingsRepo->get('smtp_port', 25);
$pop3Port = $settingsRepo->get('pop3_port', 110);
?>
<!DOCTYPE html>
<html>
<head>
<title>服务管理 - 邮件服务器</title>
<meta charset="UTF-8">
<style>
body { font-family: Arial, sans-serif; margin: 0; padding: 20px; background: #f5f5f5; }
.header { background: #007bff; color: white; padding: 15px; margin: -20px -20px 20px -20px; }
.menu { background: white; padding: 10px; margin-bottom: 20px; border-radius: 5px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
.menu a { margin-right: 15px; text-decoration: none; color: #007bff; }
.container { background: white; padding: 20px; border-radius: 5px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
.message { background: #d4edda; color: #155724; padding: 12px; border-radius: 5px; margin-bottom: 20px; }
.error { background: #f8d7da; color: #721c24; padding: 12px; border-radius: 5px; margin-bottom: 20px; }
.service-box { border: 1px solid #ddd; padding: 20px; margin-bottom: 20px; border-radius: 5px; }
.service-box h3 { margin-top: 0; }
.status { display: inline-block; padding: 6px 12px; border-radius: 4px; font-weight: 500; margin-right: 10px; }
.status-running { background: #28a745; color: white; }
.status-stopped { background: #dc3545; color: white; }
.btn { padding: 8px 16px; border: none; border-radius: 4px; cursor: pointer; text-decoration: none; display: inline-block; }
.btn-success { background: #28a745; color: white; }
.btn-danger { background: #dc3545; color: white; }
.info { color: #666; font-size: 14px; margin-top: 10px; }
.note { background: #fff3cd; border: 1px solid #ffc107; padding: 15px; border-radius: 5px; margin-top: 20px; }
</style>
</head>
<body>
<div class="header">
<h1>邮件服务器管理后台</h1>
<div>欢迎, <?php echo htmlspecialchars($_SESSION['username']); ?>
(<a href="logout.php" style="color: white;">退出</a>)
</div>
</div>
<div class="menu">
<a href="index.php">仪表盘</a>
<a href="users.php">用户管理</a>
<a href="broadcast.php">群发邮件</a>
<a href="filters.php">过滤规则</a>
<a href="logs.php">系统日志</a>
<a href="services.php">服务管理</a>
<a href="settings.php">系统设置</a>
<a href="help.php">帮助</a>
</div>
<div class="container">
<h2>服务管理</h2>
<?php if ($message): ?>
<div class="message"><?php echo $message; ?></div>
<?php endif; ?>
<?php if ($error): ?>
<div class="error"><?php echo $error; ?></div>
<?php endif; ?>
<!-- SMTP服务 -->
<div class="service-box">
<h3>SMTP服务邮件发送</h3>
<p>
<span class="status status-<?php echo $smtpRunning ? 'running' : 'stopped'; ?>">
<?php echo $smtpRunning ? '运行中' : '已停止'; ?>
</span>
<?php if ($smtpRunning): ?>
<a href="?service=smtp&action=stop" class="btn btn-danger" onclick="return confirm('确定要停止SMTP服务吗');">停止服务</a>
<?php else: ?>
<a href="?service=smtp&action=start" class="btn btn-success" onclick="return confirm('确定要启动SMTP服务吗');">启动服务</a>
<?php endif; ?>
</p>
<div class="info">
<strong>端口:</strong><?php echo $smtpPort; ?><br>
<strong>进程ID</strong><?php echo $smtpStatus['pid'] ?? '-'; ?><br>
<strong>最后启动:</strong><?php echo $smtpStatus['last_started_at'] ?? '-'; ?><br>
<strong>最后停止:</strong><?php echo $smtpStatus['last_stopped_at'] ?? '-'; ?>
</div>
</div>
<!-- POP3服务 -->
<div class="service-box">
<h3>POP3服务邮件接收</h3>
<p>
<span class="status status-<?php echo $pop3Running ? 'running' : 'stopped'; ?>">
<?php echo $pop3Running ? '运行中' : '已停止'; ?>
</span>
<?php if ($pop3Running): ?>
<a href="?service=pop3&action=stop" class="btn btn-danger" onclick="return confirm('确定要停止POP3服务吗');">停止服务</a>
<?php else: ?>
<a href="?service=pop3&action=start" class="btn btn-success" onclick="return confirm('确定要启动POP3服务吗');">启动服务</a>
<?php endif; ?>
</p>
<div class="info">
<strong>端口:</strong><?php echo $pop3Port; ?><br>
<strong>进程ID</strong><?php echo $pop3Status['pid'] ?? '-'; ?><br>
<strong>最后启动:</strong><?php echo $pop3Status['last_started_at'] ?? '-'; ?><br>
<strong>最后停止:</strong><?php echo $pop3Status['last_stopped_at'] ?? '-'; ?>
</div>
</div>
<div class="note">
<strong>注意:</strong>此页面仅用于管理服务状态。实际启动服务需要使用命令行:
<ul>
<li>SMTP服务<code>sudo php scripts/start_smtp.php</code></li>
<li>POP3服务<code>sudo php scripts/start_pop3.php</code></li>
<li>服务状态实时检测,无需手动刷新</li>
<li>启动/停止可能需要几秒钟时间</li>
<li>如果服务启动失败,请检查端口是否被占用</li>
</ul>
</div>
</div>
<!-- ===================== 新增部分:自动刷新状态 ===================== -->
<script>
// 每5秒自动检查服务状态
setInterval(function() {
fetch(window.location.href)
.then(response => response.text())
.then(html => {
// 从返回的HTML中提取运行状态
const tempDiv = document.createElement('div');
tempDiv.innerHTML = html;
// 检查SMTP状态是否变化
const smtpStatusText = tempDiv.querySelector('.service-box:nth-child(1) .status')?.textContent;
const currentSmtpStatus = document.querySelector('.service-box:nth-child(1) .status')?.textContent;
// 检查POP3状态是否变化
const pop3StatusText = tempDiv.querySelector('.service-box:nth-child(2) .status')?.textContent;
const currentPop3Status = document.querySelector('.service-box:nth-child(2) .status')?.textContent;
// 如果有变化,刷新页面
if (smtpStatusText !== currentSmtpStatus || pop3StatusText !== currentPop3Status) {
console.log('服务状态变化,刷新页面...');
location.reload();
}
})
.catch(error => console.error('状态检查失败:', error));
}, 5000);
</script>
<!-- ===================== 新增部分结束 ===================== -->
</body>
</html>