一些脚本
约 751 字大约 3 分钟
2025-08-17
静态网站部署(带日志)
#!/bin/bash
# 设置日志文件
LOG_FILE="/root/webhook/blog/deploy.log"
# 获取北京时间函数
now() {
date -d '+8 hour' +"%Y-%m-%d %H:%M:%S"
}
# 输出日志函数
log() {
echo "[$(now)] $1" | tee -a "$LOG_FILE"
}
# 错误处理函数
check() {
if [ $? -ne 0 ]; then
log "❌ $1 失败,脚本退出"
exit 1
fi
}
# 切换到项目目录
cd /root/business/blog || { log "进入项目目录失败"; exit 1; }
# 1. 安装依赖
log "开始执行: pnpm i"
pnpm i >>"$LOG_FILE" 2>&1
check "pnpm i"
log "✅ pnpm i 完成"
# 2. 构建项目
log "开始执行: pnpm build"
# pnpm build >>"$LOG_FILE" 2>&1
# check "pnpm build"
log "✅ pnpm build 完成"
# 3. 清空目标目录
TARGET_DIR="/opt/1panel/www/sites/blog.yumeng.icu/index"
log "清空目录: $TARGET_DIR"
rm -rf "${TARGET_DIR:?}/"* >>"$LOG_FILE" 2>&1
check "清空目录"
log "✅ 目录清空完成"
# 检查目标路径是否是目录,如果不是,创建目录
if [ ! -d "$TARGET_DIR" ]; then
mkdir -p "$TARGET_DIR"
log "✅ 目录 $TARGET_DIR 已创建"
fi
# 4. 移动构建文件
SRC_DIR="/root/business/blog/docs/.vuepress/dist"
log "移动构建文件: $SRC_DIR -> $TARGET_DIR"
mv "$SRC_DIR"/* "$TARGET_DIR"/ >>"$LOG_FILE" 2>&1
check "移动文件"
log "✅ 文件移动完成"
log "🎉 部署完成"
// webhook-server.js
const express = require("express");
const { exec } = require("child_process");
const path = require("path");
const app = express();
const PORT = 4000;
// 配置你的验证 token
const SECRET_TOKEN = "yumengjianghu";
// 标记当前是否有构建在执行
let building = false;
// 指定要执行的脚本路径
const SCRIPT_PATH = path.resolve(__dirname, "deploy.sh");
app.post("/webhook", (req, res) => {
// 验证请求头
const token = req.headers["x-hook-token"];
if (!token || token !== SECRET_TOKEN) {
return res.status(401).json({ success: false, message: "Unauthorized" });
}
// 检查是否有构建在执行
if (building) {
return res
.status(429)
.json({ success: false, message: "Build already in progress" });
}
// 标记构建开始
building = true;
// 立即返回响应
res.json({ success: true, message: "Build triggered" });
// 异步执行脚本
const child = exec(`bash ${SCRIPT_PATH}`, (error, stdout, stderr) => {
building = false; // 脚本执行完恢复标记
if (error) {
console.error(`❌ Script error: ${error.message}`);
return;
}
if (stderr) {
console.error(`⚠️ Script stderr: ${stderr}`);
}
console.log(`✅ Script stdout: ${stdout}`);
});
// 可选:将子进程输出实时打印到控制台
child.stdout.on("data", (data) => process.stdout.write(data));
child.stderr.on("data", (data) => process.stderr.write(data));
});
app.listen(PORT, '0.0.0.0' ,() => {
console.log(`Webhook server running on port ${PORT}`);
});
// ecosystem.config.js
module.exports = {
apps: [
{
name: "blog-hooks", // PM2 进程名字
script: "npm", // 用 npm 启动
args: "run start", // 执行 npm 脚本 start
watch: false, // 不监控文件变动
instances: 1, // 单实例运行
autorestart: true, // 崩溃或退出自动重启
max_restarts: 10, // 最大自动重启次数
restart_delay: 3000, // 重启延迟 3 秒,防止循环崩溃
env: {
NODE_ENV: "production" // 环境变量
},
out_file: "./logs/out.log", // 标准输出日志
error_file: "./logs/error.log",// 错误日志
log_date_format: "YYYY-MM-DD HH:mm:ss"
}
]
};
pm2 start ecosystem.config.js
pm2 status # 状态
pm2 logs blog-hooks # 日志
pm2 stop blog-hooks
pm2 restart blog-hooks
pm2 delete blog-hooks
# 开机自启动
pm2 startup
pm2 save
pm2 startup
会生成对应系统的自启动命令。
pm2 save
会保存当前进程列表,下次开机自动启动。
- 自动重启:服务崩溃或退出都会自动重启
- 防止崩溃循环:
restart_delay
+max_restarts
避免短时间重复重启 - 日志管理:输出日志和错误日志分开,并带时间戳
- 环境变量:可以区分生产/开发环境
贡献者
更新日志
2025/8/18 10:08
查看所有更新日志
85b18
-doc update于ffca1
-doc update于