共计 6119 个字符,预计需要花费 16 分钟才能阅读完成。
首先感谢这两位作者脚本提出的贡献
https://hkfires.pp.ua/blog/1496222667/
在 Serv00 上使用 Cron 进行进程保活的情况下,发现 Cron 计划任务经常被清掉,导致进程存活时间很短
这个方案利用了 Serv00 自带 Apache 服务器的 Phusion Passenger 插件功能,每次访问网页时可以唤醒 Nodejs 程序
部署步骤
首先你需要手搓一个链接来启动你需要监控的 Serv00 服务器脚本内容如下
在 install-agent.sh 脚本中添加以下代码
#!/bin/bash USERNAME=$(whoami) WORKDIR="/home/${USERNAME}/.nezha-agent" # 自定义参数部分 NZ_DASHBOARD_SERVER="your_dashboard_server" # 修改为你的 Dashboard 站点地址 NZ_DASHBOARD_PORT="5555" # 修改为你的面板 RPC 端口 NZ_DASHBOARD_PASSWORD="your_agent_secret" # 修改为你的 Agent 密钥 NZ_GRPC_PROXY="false" # 修改为 true 或 false,表示是否启用 gRPC 端口的 SSL/TLS 加密 # 下载 nezha-agent 的函数 download_agent() { DOWNLOAD_LINK="https://github.com/nezhahq/agent/releases/latest/download/nezha-agent_freebsd_amd64.zip" if ! wget -qO "$ZIP_FILE" "$DOWNLOAD_LINK"; then echo 'error: Download failed! Please check your network or try again.' return 1 fi return 0 } # 解压函数 decompression() { unzip "$1" -d "$TMP_DIRECTORY" EXIT_CODE=$? if [${EXIT_CODE} -ne 0 ]; then rm -r "$TMP_DIRECTORY" echo "removed: $TMP_DIRECTORY" exit 1 fi } # 安装 nezha-agent 的函数 install_agent() {install -m 755 ${TMP_DIRECTORY}/nezha-agent ${WORKDIR}/nezha-agent } # 生成 config.yml 的函数 generate_config() {CONFIG_PATH="${WORKDIR}/config.yml" cat > "$CONFIG_PATH" << EOF client_secret: ${NZ_DASHBOARD_PASSWORD} debug: false disable_auto_update: false disable_command_execute: false disable_force_update: false disable_nat: false disable_send_query: false gpu: false insecure_tls: false ip_report_period: 1800 report_delay: 1 server: ${NZ_DASHBOARD_SERVER}:${NZ_DASHBOARD_PORT} skip_connection_count: false skip_procs_count: false temperature: false tls: ${NZ_GRPC_PROXY} use_gitee_to_upgrade: false use_ipv6_country_code: false uuid: EOF echo "config.yml 已成功生成到 ${CONFIG_PATH}" } # 生成启动脚本的函数 generate_run_agent() {if [ -z "${NZ_DASHBOARD_SERVER}" ] || [-z "${NZ_DASHBOARD_PASSWORD}" ]; then echo "error! 所有选项都不能为空 " return 1 rm -rf ${WORKDIR} exit fi generate_config cat > ${WORKDIR}/start.sh << EOF #!/bin/bash pgrep -f 'nezha-agent' | xargs -r kill cd ${WORKDIR} TMPDIR="${WORKDIR}" exec ${WORKDIR}/nezha-agent -c config.yml >/dev/null 2>&1 EOF chmod +x ${WORKDIR}/start.sh } # 启动 nezha-agent 的函数 run_agent() {nohup ${WORKDIR}/start.sh >/dev/null 2>&1 & printf " 正在启动 nezha-agent,请耐心等待...\n" sleep 3 if pgrep -f "nezha-agent -c" > /dev/null; then echo "nezha-agent 已启动!" echo " 如果面板处未上线,请检查参数是否填写正确,并停止 agent 进程,删除已安装的 agent 后重新安装!" echo " 停止 agent 进程的命令:pgrep -f 'nezha-agent' | xargs -r kill" echo " 删除已安装的 agent 的命令:rm -rf ~/.nezha-agent" echo echo " 如果你想使用 pm2 管理 agent 进程,请执行:pm2 start ~/.nezha-agent/start.sh --name nezha-agent" else rm -rf "${WORKDIR}" echo "nezha-agent 启动失败,请检查参数填写是否正确,并重新安装!" fi } # 主程序 mkdir -p ${WORKDIR} cd ${WORKDIR} TMP_DIRECTORY="$(mktemp -d)" ZIP_FILE="${TMP_DIRECTORY}/nezha-agent_freebsd_amd64.zip" [! -e ${WORKDIR}/start.sh ] && generate_run_agent [! -e ${WORKDIR}/nezha-agent ] && download_agent \ && decompression "${ZIP_FILE}" \ && install_agent rm -rf "${TMP_DIRECTORY}" [-e ${WORKDIR}/start.sh ] && run_agent
安装完监控以后开始添加域名
当然你也可以使用自带的域名
SSH 登录 Serv00,输入 cd domains/ 你的网站域名 /public_nodejs/
执行
mv public static
npm22 install express
npm install express morgan
新建个名为 app.js 的文件,粘贴以下内容,把
Serv00 登录用户名
修改成你自己的 Serv00 用户名
const express = require("express"); const path = require("path"); const fs = require("fs"); const {exec} = require("child_process"); const app = express(); const port = 3000; // 配置参数 const user = "Serv00 登录用户名 "; const processCommand = "/home/${user}/.nezha-agent/nezha-agent -c /home/${user}/.nezha-agent/config.yml"; const logDir = "/home/${user}/domains/ 你的域名 /logs"; const statusLogPath = path.join(logDir, "nz.log"); // 初始化日志目录 !fs.existsSync(logDir) && fs.mkdirSync(logDir, { recursive: true}); // 增强版日志清理(保留当前日志)function cleanLogs() { try {const now = Date.now(); const files = fs.readdirSync(logDir); files.forEach(file => { // 跳过当前状态日志 if (file === "nz.log") return; const filePath = path.join(logDir, file); const stats = fs.statSync(filePath); // 删除 10 分钟前的日志文件 if ((now - stats.mtimeMs) > 600000) {fs.unlinkSync(filePath); console.log(` 已清理过期日志: ${file}`); } }); // 日志轮换(保留最新 5 个)const logFiles = fs.readdirSync(logDir) .filter(f => f.startsWith("nz.log.")) .sort() .reverse(); if (logFiles.length > 5) {logFiles.slice(5).forEach(f => {fs.unlinkSync(path.join(logDir, f)); }); } } catch (err) {console.error(" 日志清理失败:", err); } } // 带日志轮换的进程检查 function checkProcessAlive() {exec(`pgrep -u ${user} -f '${processCommand}'`, (err, stdout) => {const timestamp = new Date().toISOString(); const status = err || !stdout.trim() ? "down" : "up"; // 每日日志轮换 if (!fs.existsSync(statusLogPath)) {const rotatedLog = path.join(logDir, `nz.log.${new Date().toISOString().split('T')[0]}`); fs.existsSync(rotatedLog) || fs.copyFileSync(statusLogPath, rotatedLog); } // 写入状态日志 fs.appendFile(statusLogPath, `[${timestamp}] Process ${status}\n`, (err) => {err && console.error(" 状态写入失败:", err); }); if (status === "down") {exec(`nohup ${processCommand} >> ${logDir}/nezha.log 2>&1 &`, (err) => err && console.error(" 进程启动失败:", err) ); } }); } // 日志查看路由(实时读取)app.get("/status-log", (req, res) => {fs.readFile(statusLogPath, "utf8", (err, data) => {if (err) {res.status(500).type("text/plain").send(" 日志暂不可用 "); } else {res.type("text/plain").send(data); } }); }); // 静态文件服务 app.use(express.static(path.join(__dirname, "static"))); // 前端页面路由 app.get("/", (req, res) => {res.sendFile(path.join(__dirname, "static/index.html")); }); // 启动定时任务 setInterval(checkProcessAlive, 5000); // 5 秒进程检查 setInterval(cleanLogs, 600000); // 10 分钟清理周期 app.listen(port, () => { console.log(` 服务运行中:- 监控页面:http://localhost:${port} - 实时日志:${statusLogPath}`); });
再将 app.js 上传到服务器,完整路径是 /home/ 你的用户名 /domains/ 你的网站域名 /public_nodejs/,修改完成后 public_nodejs 目录下应该和我一样
需要你在日志目录下创建 nz.log 文件
如果服务启动不了请查看日志目录下 error.log
配套前端页面(static/index.html):
<!DOCTYPE html> <html> <head> <title> 进程状态监控 </title> <style> #log-container { background: #1a1a1a; color: #00ff00; padding: 20px; margin: 20px; border-radius: 5px; max-height: 70vh; overflow: auto; font-family: 'Courier New', monospace; white-space: pre-wrap; } .timestamp {color: #888;} </style> </head> <body> <h1 id='pk-menu-0'>Nezha 进程状态监控 </h1> <div id="log-container"> 正在加载实时日志...</div> <script> const logContainer = document.getElementById('log-container'); async function updateLogs() { try {const response = await fetch('/status-log'); const rawText = await response.text(); const formattedText = rawText .split('\n') .map(line => line.replace(/($$\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$$)/, '<span class="timestamp">$1</span>' )) .join('\n'); logContainer.innerHTML = formattedText; logContainer.scrollTop = logContainer.scrollHeight; } catch (err) {logContainer.textContent = '日志更新失败:' + err.message;} } // 每 2 秒更新 + 首次加载 setInterval(updateLogs, 2000); updateLogs(); </script> </body> </html>
测试
每当我们杀死程序的时候又会自己启动
网页监控随便找个都行,市面上有很多免费的
自动化网页监控项目推荐upptime,不需要有服务器,只需要有 Github 账号就能够进行部署
后续
可能清理日记还有些问题等以后优化吧