公司有些項目環境沒有接入 jenkins 是以部署起來比較麻煩,是以寫個腳本節約部署時間。
背景
前端項目分開發、測試、生産環境,開發及測試已接入 jenkins 自動部署,生産環境依然還是手動。每次都需要進行本地打包, 手動壓縮上傳到伺服器目錄,ssh 登入伺服器後備份舊檔案, 手動删除檔案再将包解壓到指定目錄,操作流程比較繁瑣,需要提前了解伺服器部署目錄,不太友好,是以就寫了個腳本簡化部署操作。
依賴安裝
部署包含壓縮檔案、ssh 登入、檔案上傳等幾個步驟,是以需要安裝如下依賴:
- archiver,壓縮檔案使用。
- node-ssh,ssh 操作。
- silly-datetime,時間處理。
關鍵代碼
在項目根目錄建立 deploy.js 腳本,作用是上傳壓縮包至伺服器、備份舊檔案,解壓代碼壓縮包。
const fs = require('fs');
const path = require('path');
const archiver = require('archiver');
const { NodeSSH } = require('node-ssh');
const sd = require('silly-datetime');
let args = process.argv.splice(2),
isRollback = args.includes('rollback');
// 目前時間
let curTime = sd.format(new Date(), 'YYYYMMDDHH');
// 目前時間格式化
console.log((isRollback ? '復原' : '部署') + '時間:' + curTime);
// 設定本地 dist 檔案路徑
const distPath = path.resolve(__dirname, 'dist');
const ssh = new NodeSSH();
// 遠端伺服器配置資訊
const config = require('./config');
// 本地檔案上傳至遠端伺服器
function uploadFile() {
ssh
.connect({
host: config.host,
username: config.username,
password: config.password,
port: 22,
})
.then(() => {
console.log('SSH login success');
ssh
.putFile(
`${__dirname}/dist${curTime}.zip`,
`${config.pathUrl}/dist${curTime}.zip`
)
.then(() => {
console.log('The zip file is upload successful');
remoteFileUpdate();
})
.catch((err) => {
console.log('the file upload fail:', err);
process.exit(0);
});
})
.catch((err) => {
console.log('SSH conneting fail:', err);
process.exit(0);
});
}
// 遠端檔案更新
const remoteFileUpdate = () => {
let cmd = isRollback
? `rm dist && mv dist.bak${curTime} dist`
: `mv dist dist.bak${curTime} && unzip dist${curTime}.zip`;
ssh
.execCommand(cmd, {
cwd: config.pathUrl,
})
.then((result) => {
console.log(`The update message is: ${result.stdout}`);
if (!result.stderr) {
console.log('Gratefule! update success!');
process.exit(0);
} else {
console.log('Something wrong:', result);
process.exit(0);
}
});
};
// 本地檔案壓縮
const zipDirector = () => {
const output = fs.createWriteStream(`${__dirname}/dist${curTime}.zip`);
const archive = archiver('zip', {
zlib: { level: 9 },
}).on('error', (err) => {
throw err;
});
output.on('close', (err) => {
if (err) {
console.log('something error width the zip process:', err);
return;
}
uploadFile();
console.log(`${archive.pointer()} total bytes`);
console.log(
'archiver has been finalized and the output file descriptor has closed.'
);
});
output.on('end', () => {
console.log('Data has been drained');
});
archive.pipe(output);
archive.directory(distPath, '/dist');
archive.finalize();
};
// 復原代碼
if (isRollback) {
remoteFileUpdate();
} else {
// 更新代碼
zipDirector();
}
伺服器上的備份,解壓等操作是通過執行 shell 指令做的,你也可以自己預先寫好相關腳本去執行。
使用方法
在根目錄建立一個
config.js
用于存放伺服器 IP、使用者名、密碼、部署目錄等資訊,然後就可以在 package.json 中追加指令去調用上面的 node 腳本。
"scripts": {
"deploy": "node deploy.js",
"rollback": "node deploy.js rollback"
}
執行指令執行相應操作:
-
,部署 + 備份。npm run deploy
-
,復原代碼。npm run rollback