import paramiko client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect('152.136.232.83', port=22, username='root', password='Jianhua105', timeout=10) def run(cmd): print(f"\n>>> {cmd[:120]}") stdin, stdout, stderr = client.exec_command(cmd, timeout=20) out = stdout.read().decode('utf-8', errors='replace').strip() err = stderr.read().decode('utf-8', errors='replace').strip() if out: print(out[-600:]) if err: print(f"ERR: {err[-200:]}") return out patch_code = r"""const fs = require('fs'); const filePath = '/www/wwwroot/zhinengtiapp/index.js'; let content = fs.readFileSync(filePath, 'utf-8'); const marker = "// \u6587\u6848\u751f\u6210\uff08\u5f02\u6b65\uff1a\u7acb\u5373\u8fd4\u56de\uff0c\u540e\u53f0\u5904\u7406\uff09"; if (content.includes('/api/system/config/public')) { console.log('SKIP: endpoint already exists'); process.exit(0); } const newEndpoint = ` // ========== \u81ea\u52a8\u66f4\u65b0\u914d\u7f6e\u63a5\u53e3 ========== app.get('/api/system/config/public', (req, res) => { const sysCfg = loadSysConfig() const envPath = path.join(__dirname, '.env') let cosBucket = '' let cosRegion = '' try { const envContent = fs.readFileSync(envPath, 'utf-8') envContent.split(String.fromCharCode(10)).forEach(line => { line = line.trim() if (!line || line.startsWith('#')) return const eqIdx = line.indexOf('=') if (eqIdx > 0) { const key = line.substring(0, eqIdx).trim() const val = line.substring(eqIdx + 1).trim() if (key === 'COS_BUCKET') cosBucket = val if (key === 'COS_REGION') cosRegion = val } }) } catch (e) {} cosBucket = sysCfg.UPDATE_COS_BUCKET || cosBucket cosRegion = sysCfg.UPDATE_COS_REGION || cosRegion const updatePath = sysCfg.UPDATE_COS_PATH || 'updates' let updateUrl = '' if (cosBucket && cosRegion) { updateUrl = 'https://' + cosBucket + '.cos.' + cosRegion + '.myqcloud.com/' + updatePath } res.json({ success: true, update_url: updateUrl }) }) `; const idx = content.indexOf(marker); if (idx === -1) { console.log('ERROR: marker not found'); process.exit(1); } content = content.slice(0, idx) + newEndpoint + content.slice(idx); fs.writeFileSync(filePath, content, 'utf-8'); console.log('OK: patched index.js'); """ sftp = client.open_sftp() with sftp.open('/tmp/patch_index2.js', 'w') as f: f.write(patch_code) sftp.close() print("Uploaded patch_index2.js") # Backup current (already restored) file run("cp /www/wwwroot/zhinengtiapp/index.js /www/wwwroot/zhinengtiapp/index.js.bak2") # Run patch run("node /tmp/patch_index2.js") # Verify syntax run("node --check /www/wwwroot/zhinengtiapp/index.js 2>&1") # Check endpoint exists run("grep -n 'system/config/public' /www/wwwroot/zhinengtiapp/index.js") # Restart run("pm2 restart ai-video 2>&1") run("sleep 3 && pm2 list") # Test run("curl -s http://localhost:3001/api/system/config/public") client.close() print("\n=== PATCH DONE ===")