共计 6116 个字符,预计需要花费 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):
<style>
#log-container {<br /> background: #1a1a1a;<br /> color: #00ff00;<br /> padding: 20px;<br /> margin: 20px;<br /> border-radius: 5px;<br /> max-height: 70vh;<br /> overflow: auto;<br /> font-family: 'Courier New', monospace;<br /> white-space: pre-wrap;<br />}<br /> .timestamp {color: #888;}<br /> </style>
<h1 id='pk-menu-1'>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>
测试

每当我们杀死程序的时候又会自己启动
网页监控随便找个都行,市面上有很多免费的
自动化网页监控项目推荐upptime,不需要有服务器,只需要有 Github 账号就能够进行部署
后续
可能清理日记还有些问题等以后优化吧