Appearance
rollback.cjs
js
const { Client } = require('ssh2')
const { projectName, config } = require('./config.cjs')
const rollback = () => {
return new Promise((resolve, reject) => {
const conn = new Client()
conn
.on('ready', () => {
console.log('✅ SSH 连接成功,准备回滚')
// 1. 进入目录
// 2. 查找所有 bak 目录,按名称排序取最新
// 3. 判断是否存在备份
// 4. 当前先备份一份,再替换
const cmd = `cd "${config.targetParentDir}" \
&& bak_dirs=($(ls -d ${projectName}_bak_* 2>/dev/null | sort)) \
&& if [ \${#bak_dirs[@]} -eq 0 ]; then echo "❌ 没有找到任何备份文件夹,无法回滚"; exit 1; fi \
&& latest_bak=\${bak_dirs[-1]} \
&& echo "👉 找到最新备份:\$latest_bak" \
&& if [ -d "${projectName}" ]; then mv "${projectName}" "${projectName}_before_rollback_\$(date +%Y%m%d_%H%M%S)"; fi \
&& mv "\$latest_bak" "${projectName}" \
&& echo "🎉 回滚完成,已恢复:\$latest_bak → ${projectName}"`
conn.exec(cmd, (err, stream) => {
if (err) return reject(err)
stream.on('close', code => {
if (code === 0) {
console.log('✅ 回滚脚本执行成功')
resolve()
} else {
reject(new Error(`回滚命令退出码 ${code}`))
}
conn.end()
})
stream.on('data', d => console.log('stdout:', d.toString()))
stream.stderr.on('data', d => console.log('stderr:', d.toString()))
})
})
.on('error', e => reject(e))
.connect(config)
})
}
;(async () => {
try {
await rollback()
} catch (err) {
console.error('❌ 回滚失败:', err.message)
process.exit(1)
}
})()