const { Client } = require('ssh2'); const fs = require('fs'); const path = require('path'); const SERVER = { host: '119.45.10.34', port: 22, username: 'root', password: '#xyzh%CS#2512@28' }; const REMOTE_DIR = '/www/wwwroot/demo.tensorgrove.com.cn/server'; const FILES = [ { local: path.join(__dirname, '..', 'services', 'assistantProfileConfig.js'), remote: REMOTE_DIR + '/services/assistantProfileConfig.js', }, ]; function sshExec(client, cmd) { return new Promise((resolve, reject) => { client.exec(cmd, (err, stream) => { if (err) return reject(err); let out = '', errOut = ''; stream.on('data', (d) => (out += d.toString())); stream.stderr.on('data', (d) => (errOut += d.toString())); stream.on('close', (code) => resolve({ out: out.trim(), err: errOut.trim(), code })); }); }); } function sshUpload(client, localPath, remotePath) { return new Promise((resolve, reject) => { client.sftp((err, sftp) => { if (err) return reject(err); sftp.fastPut(localPath, remotePath, (err) => { if (err) return reject(err); resolve(); }); }); }); } async function deploy() { const client = new Client(); client.on('ready', async () => { try { console.log('✅ SSH connected\n'); const ts = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19); // 1. 先查看服务器当前prompt console.log('📋 服务器当前prompt:'); const before = await sshExec(client, `grep -n 'buildKnowledgeAnswerPrompt\\|知识库涵盖\\|产品用法' ${REMOTE_DIR}/services/assistantProfileConfig.js | head -5`); console.log(' ' + (before.out || '(not found)') + '\n'); // 2. 备份 + 上传 for (const { local, remote } of FILES) { const name = path.basename(remote); await sshExec(client, `cp ${remote} ${remote}.bak_${ts}`); console.log('📦 Backup: ' + name); await sshUpload(client, local, remote); console.log('📤 Uploaded: ' + name); const syntax = await sshExec(client, `node -c ${remote}`); if (syntax.code !== 0) { console.error('❌ Syntax error in ' + name + '! Rolling back...'); await sshExec(client, `cp ${remote}.bak_${ts} ${remote}`); client.end(); return; } console.log('🔍 Syntax OK: ' + name + '\n'); } // 3. 重启PM2 const pm2Result = await sshExec(client, `cd ${REMOTE_DIR} && pm2 restart all --update-env`); console.log('🔄 PM2 restarted'); if (pm2Result.out) console.log(' ' + pm2Result.out.split('\n').slice(0, 3).join('\n ')); await new Promise(r => setTimeout(r, 5000)); // 4. 验证新prompt已生效 console.log('\n📋 服务器新prompt:'); const after = await sshExec(client, `grep -n '知识库涵盖\\|产品常有别名\\|不得编造' ${REMOTE_DIR}/services/assistantProfileConfig.js | head -5`); console.log(' ' + (after.out || '(not found)')); // 5. PM2 状态 const status = await sshExec(client, 'pm2 status'); console.log('\n📊 PM2 Status:'); console.log(' ' + status.out.split('\n').slice(0, 6).join('\n ')); console.log('\n✅ 部署完成!KB answer prompt 已更新为优化版本'); } catch (e) { console.error('❌ Error:', e.message); } finally { client.end(); } }); client.on('error', (err) => console.error('❌ SSH Error:', err.message)); client.connect(SERVER); } deploy();