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_BASE = path.join(__dirname, '..', 'test2'); const filesToDeploy = [ { local: 'server/services/realtimeDialogRouting.js', remote: `${PROJECT}/server/services/realtimeDialogRouting.js`, }, { local: 'server/services/nativeVoiceGateway.js', remote: `${PROJECT}/server/services/nativeVoiceGateway.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('=== 部署一成系统 ASR 别名修复 ==='); const backupDir = `${PROJECT}/server/_backup_${Date.now()}`; await sshExec(`mkdir -p ${backupDir} && cp ${PROJECT}/server/services/realtimeDialogRouting.js ${PROJECT}/server/services/nativeVoiceGateway.js ${backupDir}/`); console.log('备份目录:', backupDir); for (const item of filesToDeploy) { const localPath = path.join(LOCAL_BASE, item.local.replace(/\//g, path.sep)); await sshUpload(localPath, item.remote); console.log('上传完成:', item.remote); } 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 ${PROJECT}/server/services/realtimeDialogRouting.js ${PROJECT}/server/services/nativeVoiceGateway.js 2>&1`); console.log(verify.stdout); } main().catch((e) => { console.error('Fatal:', e.message); process.exit(1); });