142 lines
5.5 KiB
JavaScript
142 lines
5.5 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_BASE = path.join(__dirname, '..', 'test2');
|
||
|
|
|
||
|
|
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);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
const filesToDeploy = [
|
||
|
|
// 服务端文件
|
||
|
|
{ local: 'server/services/toolExecutor.js', remote: `${PROJECT}/server/services/toolExecutor.js`, desc: '知识库回答精准度修复' },
|
||
|
|
{ local: 'server/services/nativeVoiceGateway.js', remote: `${PROJECT}/server/services/nativeVoiceGateway.js`, desc: '语音连接提前ready+超时兜底' },
|
||
|
|
// 客户端构建产物
|
||
|
|
{ local: 'client/dist/index.html', remote: `${PROJECT}/client/dist/index.html`, desc: '客户端入口' },
|
||
|
|
{ local: 'client/dist/assets/index-DFs3zFyd.css', remote: `${PROJECT}/client/dist/assets/index-DFs3zFyd.css`, desc: '客户端样式' },
|
||
|
|
{ local: 'client/dist/assets/index-DiJ8zsnj.js', remote: `${PROJECT}/client/dist/assets/index-DiJ8zsnj.js`, desc: '客户端JS(含getUserMedia并行化+超时)' },
|
||
|
|
];
|
||
|
|
|
||
|
|
async function main() {
|
||
|
|
console.log('=== 语音通话延迟修复 + 知识库精准度修复 部署 ===\n');
|
||
|
|
|
||
|
|
// 1. 备份
|
||
|
|
console.log('--- 1. 备份服务器文件 ---');
|
||
|
|
const backupDir = `${PROJECT}/server/_backup_${Date.now()}`;
|
||
|
|
const backupCmd = [
|
||
|
|
`mkdir -p ${backupDir}`,
|
||
|
|
`cp ${PROJECT}/server/services/toolExecutor.js ${backupDir}/`,
|
||
|
|
`cp ${PROJECT}/server/services/nativeVoiceGateway.js ${backupDir}/`,
|
||
|
|
`mkdir -p ${backupDir}/client_dist_assets`,
|
||
|
|
`cp -r ${PROJECT}/client/dist/assets/* ${backupDir}/client_dist_assets/ 2>/dev/null || true`,
|
||
|
|
`cp ${PROJECT}/client/dist/index.html ${backupDir}/client_dist_index.html 2>/dev/null || true`,
|
||
|
|
].join(' && ');
|
||
|
|
const backupResult = await sshExec(backupCmd);
|
||
|
|
console.log(`备份目录: ${backupDir}`);
|
||
|
|
if (backupResult.stderr && !backupResult.stderr.includes('true')) console.log(backupResult.stderr);
|
||
|
|
|
||
|
|
// 2. 确保远程目录存在
|
||
|
|
console.log('\n--- 2. 确保目录存在 ---');
|
||
|
|
await sshExec(`mkdir -p ${PROJECT}/client/dist/assets`);
|
||
|
|
console.log('OK');
|
||
|
|
|
||
|
|
// 3. 清理旧的客户端资源文件
|
||
|
|
console.log('\n--- 3. 清理旧客户端资源 ---');
|
||
|
|
const cleanResult = await sshExec(`rm -f ${PROJECT}/client/dist/assets/index-*.js ${PROJECT}/client/dist/assets/index-*.css 2>&1`);
|
||
|
|
console.log(cleanResult.stdout || 'OK');
|
||
|
|
|
||
|
|
// 4. 上传文件
|
||
|
|
console.log('\n--- 4. 上传文件 ---');
|
||
|
|
for (const { local, remote, desc } of filesToDeploy) {
|
||
|
|
const localPath = path.join(LOCAL_BASE, local.replace(/\//g, path.sep));
|
||
|
|
try {
|
||
|
|
if (!fs.existsSync(localPath)) {
|
||
|
|
console.log(`⚠️ 跳过 ${local} (本地文件不存在)`);
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
await sshUpload(localPath, remote);
|
||
|
|
const size = fs.statSync(localPath).size;
|
||
|
|
console.log(`✅ ${local} → ${remote} (${size}B) [${desc}]`);
|
||
|
|
} catch (e) {
|
||
|
|
console.error(`❌ ${local}: ${e.message}`);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 5. 重启 PM2
|
||
|
|
console.log('\n--- 5. 重启 PM2 ---');
|
||
|
|
const restart = await sshExec('pm2 restart bigwo-server 2>&1');
|
||
|
|
console.log(restart.stdout);
|
||
|
|
|
||
|
|
// 6. 等待检查
|
||
|
|
console.log('--- 6. 等待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);
|
||
|
|
|
||
|
|
// 7. 检查启动日志
|
||
|
|
console.log('--- 7. 启动日志 ---');
|
||
|
|
const logs = await sshExec('pm2 logs bigwo-server --nostream --lines 15 2>&1');
|
||
|
|
console.log(logs.stdout);
|
||
|
|
if (logs.stderr) console.log(logs.stderr);
|
||
|
|
|
||
|
|
// 8. 验证文件
|
||
|
|
console.log('--- 8. 验证文件行数 ---');
|
||
|
|
const wc = await sshExec(`wc -l ${PROJECT}/server/services/toolExecutor.js ${PROJECT}/server/services/nativeVoiceGateway.js 2>&1`);
|
||
|
|
console.log(wc.stdout);
|
||
|
|
|
||
|
|
const lsAssets = await sshExec(`ls -la ${PROJECT}/client/dist/assets/ 2>&1`);
|
||
|
|
console.log('客户端资源文件:');
|
||
|
|
console.log(lsAssets.stdout);
|
||
|
|
|
||
|
|
console.log('\n=== 部署完成 ===');
|
||
|
|
}
|
||
|
|
|
||
|
|
main().catch(e => { console.error('Fatal:', e.message); process.exit(1); });
|