Serv00简便、安全应用保活方案
Serv00服务器经常出现删除cron现象,通过外部SSH访问重设比较麻烦,同一个IP对多服务器SSH访问,还可能会被批量查封。
可以借用web进行应用保活,简单又安全,方法如下:
替换public_html目录下的默认主页
删除/home/${YOURNAME}/domains/${YOURNAME}.serv00.net/public_html
目录下的index.html,增加:
index.php:<?php // 引入配置文件 $config = include 'config.php'; // 日志文件路径 $logFile = 'log/access.log'; // Nginx 默认页面 HTML 内容 $nginxDefaultHtml = <<<HTML <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html> HTML; // 确保 log 目录存在 if (!is_dir('log')) { mkdir('log', 0777, true); // 创建目录,允许所有用户读写执行 } // 获取请求路径 (从 GET 参数中获取) $requestPath = $_GET['path'] ?? ''; // 记录访问日志 $logMessage = date('Y-m-d H:i:s') . " - Access: " . ($requestPath ? '?path=' . $requestPath : 'Direct Access') . "\n"; file_put_contents($logFile, $logMessage, FILE_APPEND); // 移除多余的斜杠 $requestPath = trim($requestPath, '/'); // 添加前导斜杠,使其与配置文件中的路由匹配 if ($requestPath !== '') { $requestPath = '/' . $requestPath; } // 查找匹配的配置项 $action = null; foreach ($config['routes'] as $route => $actionConfig) { if ($route === $requestPath) { $action = $actionConfig; break; } } if ($action) { // 执行对应操作 switch ($action['type']) { case 'command': $command = $action['command']; $logMessage = date('Y-m-d H:i:s') . " - Executing command: " . $command . "\n"; file_put_contents($logFile, $logMessage, FILE_APPEND); // 执行命令并获取输出 $output = shell_exec($command . ' 2>&1'); // 2>&1 将标准错误重定向到标准输出 $logMessage = date('Y-m-d H:i:s') . " - Command output: " . $output . "\n"; file_put_contents($logFile, $logMessage, FILE_APPEND); echo "<pre>" . htmlspecialchars($output) . "</pre>"; // 使用 <pre> 标签保持格式,并进行HTML转义 break; case 'static': $filePath = $action['file']; if (is_dir($filePath)) { // 目录托管 $requestedFile = realpath($filePath . '/' . ltrim($requestPath, '/')); // 确保在目录内 $logMessage = date('Y-m-d H:i:s') . " - Serving static directory: " . $filePath . ", Requested file: " . $requestedFile . "\n"; file_put_contents($logFile, $logMessage, FILE_APPEND); if ($requestedFile && strpos($requestedFile, realpath($filePath)) === 0 && file_exists($requestedFile) && is_readable($requestedFile)) { // 安全检查 // 根据文件类型设置 Content-Type $fileExtension = pathinfo($requestedFile, PATHINFO_EXTENSION); $contentType = getContentType($fileExtension); // 使用函数获取 Content-Type header('Content-Type: ' . $contentType); readfile($requestedFile); } else { header("HTTP/1.0 404 Not Found"); echo "<h1>404 Not Found</h1>"; $logMessage = date('Y-m-d H:i:s') . " - Static file not found: " . $filePath . '/' . ltrim($requestPath, '/') . "\n"; file_put_contents($logFile, $logMessage, FILE_APPEND); } } elseif (file_exists($filePath) && is_readable($filePath)) { // 单个文件 $logMessage = date('Y-m-d H:i:s') . " - Serving static file: " . $filePath . "\n"; file_put_contents($logFile, $logMessage, FILE_APPEND); // 根据文件类型设置 Content-Type $fileExtension = pathinfo($filePath, PATHINFO_EXTENSION); $contentType = getContentType($fileExtension); // 使用函数获取 Content-Type header('Content-Type: ' . $contentType); readfile($filePath); } else { header("HTTP/1.0 404 Not Found"); echo "<h1>404 Not Found</h1>"; $logMessage = date('Y-m-d H:i:s') . " - Static file not found: " . $filePath . "\n"; file_put_contents($logFile, $logMessage, FILE_APPEND); } break; default: header("HTTP/1.0 500 Internal Server Error"); echo "<h1>500 Internal Server Error</h1><p>Invalid action type.</p>"; $logMessage = date('Y-m-d H:i:s') . " - Invalid action type: " . $action['type'] . "\n"; file_put_contents($logFile, $logMessage, FILE_APPEND); break; } } else { // 未找到匹配的路由,返回 Nginx 默认页面 header('Content-Type: text/html'); echo $nginxDefaultHtml; $logMessage = date('Y-m-d H:i:s') . " - Route not found, serving Nginx default page.\n"; file_put_contents($logFile, $logMessage, FILE_APPEND); } /** * 根据文件扩展名获取 Content-Type * @param string $extension * @return string */ function getContentType(string $extension): string { $mimeTypes = [ 'html' => 'text/html', 'css' => 'text/css', 'js' => 'text/javascript', 'json' => 'application/json', 'xml' => 'application/xml', 'txt' => 'text/plain', 'jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'png' => 'image/png', 'gif' => 'image/gif', 'svg' => 'image/svg+xml', // 添加更多 mime 类型 ]; return $mimeTypes[$extension] ?? 'application/octet-stream'; // 默认 } ?>
config.php:
<?php
return [
'routes' => [
'/status' => [
'type' => 'command',
'command' => 'uptime'
],
'/diskspace' => [
'type' => 'command',
'command' => 'df -h'
],
'/cron' => [
'type' => 'command',
'command' => 'bash ./your_check_cron_shell.sh'
],
'/installcron' => [
'type' => 'command',
'command' => '(crontab -l 2>/dev/null; echo "00 08 * * 6 ${your_command} > /dev/null 2>&1") | crontab -'
],
'/back.html' => [
'type' => 'static',
'file' => 'your.html' // 单个文件
]
]
];
按需修改上面的配置文件对应的脚本或命令,尽情发挥。
WEB远程调用示例
https://${YOURNAME}.serv00.net/?path=cron