111 lines
4.1 KiB
JavaScript
111 lines
4.1 KiB
JavaScript
|
|
import { Client } from "ssh2";
|
||
|
|
import { readFileSync } from "fs";
|
||
|
|
import { join } from "path";
|
||
|
|
|
||
|
|
const SSH_CONFIG = {
|
||
|
|
host: "119.45.10.34",
|
||
|
|
port: 22,
|
||
|
|
username: "root",
|
||
|
|
password: "#xyzh%CS#2512@28",
|
||
|
|
readyTimeout: 10000,
|
||
|
|
};
|
||
|
|
|
||
|
|
function sshExec(command, timeout = 30000) {
|
||
|
|
return new Promise((resolve, reject) => {
|
||
|
|
const conn = new Client();
|
||
|
|
let stdout = "";
|
||
|
|
let stderr = "";
|
||
|
|
let timer = setTimeout(() => {
|
||
|
|
conn.end();
|
||
|
|
resolve({ stdout, stderr: stderr + "\n[TIMEOUT]", code: -1 });
|
||
|
|
}, timeout);
|
||
|
|
conn.on("ready", () => {
|
||
|
|
conn.exec(command, (err, stream) => {
|
||
|
|
if (err) { clearTimeout(timer); conn.end(); return reject(err); }
|
||
|
|
stream.on("close", (code) => { clearTimeout(timer); conn.end(); resolve({ stdout, stderr, code }); });
|
||
|
|
stream.on("data", (d) => { stdout += d.toString(); });
|
||
|
|
stream.stderr.on("data", (d) => { stderr += d.toString(); });
|
||
|
|
});
|
||
|
|
}).on("error", (err) => { clearTimeout(timer); reject(err); }).connect(SSH_CONFIG);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
function sshUpload(localPath, remotePath) {
|
||
|
|
return new Promise((resolve, reject) => {
|
||
|
|
const conn = new Client();
|
||
|
|
conn.on("ready", () => {
|
||
|
|
conn.sftp((err, sftp) => {
|
||
|
|
if (err) { conn.end(); return reject(err); }
|
||
|
|
const content = readFileSync(localPath);
|
||
|
|
const ws = sftp.createWriteStream(remotePath);
|
||
|
|
ws.on("close", () => { conn.end(); resolve(); });
|
||
|
|
ws.on("error", (e) => { conn.end(); reject(e); });
|
||
|
|
ws.write(content);
|
||
|
|
ws.end();
|
||
|
|
});
|
||
|
|
}).on("error", (err) => reject(err)).connect(SSH_CONFIG);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
const PROJECT = "/www/wwwroot/demo.tensorgrove.com.cn";
|
||
|
|
const LOCAL_BASE = "C:\\Users\\UI\\Desktop\\bigwo\\test2";
|
||
|
|
|
||
|
|
async function main() {
|
||
|
|
const filesToDeploy = [
|
||
|
|
{ local: "server\\routes\\voice.js", remote: `${PROJECT}/server/routes/voice.js` },
|
||
|
|
{ local: "server\\services\\toolExecutor.js", remote: `${PROJECT}/server/services/toolExecutor.js` },
|
||
|
|
{ local: "server\\config\\voiceChatConfig.js", remote: `${PROJECT}/server/config/voiceChatConfig.js` },
|
||
|
|
{ local: "server\\config\\tools.js", remote: `${PROJECT}/server/config/tools.js` },
|
||
|
|
{ local: "server\\app.js", remote: `${PROJECT}/server/app.js` },
|
||
|
|
];
|
||
|
|
|
||
|
|
// 1. 备份
|
||
|
|
console.log("=== 1. 备份服务器文件 ===");
|
||
|
|
const backupDir = `${PROJECT}/server/_backup_${Date.now()}`;
|
||
|
|
const backupResult = await sshExec(`mkdir -p ${backupDir} && cp ${PROJECT}/server/routes/voice.js ${PROJECT}/server/services/toolExecutor.js ${PROJECT}/server/config/voiceChatConfig.js ${PROJECT}/server/app.js ${backupDir}/ 2>&1`);
|
||
|
|
console.log(backupResult.stdout || "(done)");
|
||
|
|
console.log(`备份目录: ${backupDir}`);
|
||
|
|
|
||
|
|
// 2. 上传文件
|
||
|
|
console.log("\n=== 2. 上传文件 ===");
|
||
|
|
for (const { local, remote } of filesToDeploy) {
|
||
|
|
const localPath = join(LOCAL_BASE, local);
|
||
|
|
try {
|
||
|
|
await sshUpload(localPath, remote);
|
||
|
|
console.log(`✅ ${local} → ${remote}`);
|
||
|
|
} catch (e) {
|
||
|
|
console.error(`❌ ${local}: ${e.message}`);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 3. 重启 PM2
|
||
|
|
console.log("\n=== 3. 重启 PM2 ===");
|
||
|
|
const restart = await sshExec("pm2 restart bigwo-server 2>&1");
|
||
|
|
console.log(restart.stdout);
|
||
|
|
|
||
|
|
// 4. 等待 3 秒检查状态
|
||
|
|
console.log("=== 4. 等待 3 秒后检查 ===");
|
||
|
|
await new Promise(r => setTimeout(r, 3000));
|
||
|
|
|
||
|
|
const health = await sshExec(`curl -s http://127.0.0.1:3012/api/health 2>&1`);
|
||
|
|
console.log("Health:", health.stdout);
|
||
|
|
|
||
|
|
const pm2 = await sshExec("pm2 list 2>&1");
|
||
|
|
console.log(pm2.stdout);
|
||
|
|
|
||
|
|
// 5. 检查最新日志
|
||
|
|
console.log("=== 5. 启动日志 ===");
|
||
|
|
const logs = await sshExec("pm2 logs bigwo-server --nostream --lines 15 2>&1");
|
||
|
|
console.log(logs.stdout);
|
||
|
|
if (logs.stderr) console.log(logs.stderr);
|
||
|
|
|
||
|
|
// 6. 验证文件行数
|
||
|
|
console.log("=== 6. 验证文件 ===");
|
||
|
|
const wc = await sshExec(`wc -l ${PROJECT}/server/routes/voice.js ${PROJECT}/server/services/toolExecutor.js ${PROJECT}/server/config/voiceChatConfig.js ${PROJECT}/server/app.js 2>&1`);
|
||
|
|
console.log(wc.stdout);
|
||
|
|
|
||
|
|
console.log("\n=== 部署完成 ===");
|
||
|
|
}
|
||
|
|
|
||
|
|
main().catch(e => { console.error("Fatal:", e.message); process.exit(1); });
|