83 lines
2.7 KiB
JavaScript
83 lines
2.7 KiB
JavaScript
|
|
const { Client } = require('ssh2');
|
||
|
|
const fs = require('fs');
|
||
|
|
const path = require('path');
|
||
|
|
|
||
|
|
const SSH_CONFIG = {
|
||
|
|
host: '119.45.10.34',
|
||
|
|
port: 22,
|
||
|
|
username: 'root',
|
||
|
|
password: '#xyzh%CS#2512@28',
|
||
|
|
readyTimeout: 10000,
|
||
|
|
};
|
||
|
|
|
||
|
|
const PROJECT = '/www/wwwroot/demo.tensorgrove.com.cn';
|
||
|
|
const LOCAL_FILE = path.join(__dirname, '..', 'test2', 'server', 'services', 'realtimeDialogRouting.js');
|
||
|
|
const REMOTE_FILE = `${PROJECT}/server/services/realtimeDialogRouting.js`;
|
||
|
|
|
||
|
|
function sshExec(command, timeout = 30000) {
|
||
|
|
return new Promise((resolve, reject) => {
|
||
|
|
const conn = new Client();
|
||
|
|
let stdout = '';
|
||
|
|
let stderr = '';
|
||
|
|
const 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 = fs.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);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
async function main() {
|
||
|
|
console.log('=== 部署闲聊切换修复 ===');
|
||
|
|
const backupDir = `${PROJECT}/server/_backup_${Date.now()}`;
|
||
|
|
const backup = await sshExec(`mkdir -p ${backupDir} && cp ${REMOTE_FILE} ${backupDir}/`);
|
||
|
|
console.log('备份目录:', backupDir);
|
||
|
|
if (backup.stderr) console.log(backup.stderr);
|
||
|
|
|
||
|
|
await sshUpload(LOCAL_FILE, REMOTE_FILE);
|
||
|
|
console.log('上传完成:', REMOTE_FILE);
|
||
|
|
|
||
|
|
const restart = await sshExec('pm2 restart bigwo-server 2>&1');
|
||
|
|
console.log(restart.stdout);
|
||
|
|
|
||
|
|
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);
|
||
|
|
|
||
|
|
const verify = await sshExec(`wc -l ${REMOTE_FILE} 2>&1`);
|
||
|
|
console.log(verify.stdout);
|
||
|
|
}
|
||
|
|
|
||
|
|
main().catch((e) => {
|
||
|
|
console.error('Fatal:', e.message);
|
||
|
|
process.exit(1);
|
||
|
|
});
|