以下内容可能会造成其它语言用户的不适,敬请读者注意。
这是一个用于Nodejs项目的热部署实例,其它语言用户也可以看看,因为文中会有其它语言用到的东西。
导包
//全局命令行
require('shelljs/global');
//SSH工具
let Client = require('ssh2').Client;
//tar.gz压缩工具
let targz = require('tar.gz');
//文件模糊匹配工具
let glob = require('glob');
//文件操作类,fs的封装
let fs = require('fs-extra');
其它语言可能用到的东西
//执行命令行
exec('cd abc' , (code, stdout, stderr) => {
});
//以使用gradle编译项目为例
exec('gradle xxxx' , (code, stdout, stderr) => {
if (stderr) {
console.error(stderr);
} else {
//下一步
}
});
删除并重新创建临时归档文件夹
const ROOT = './compress';
const ROOT_TAR_GZ = `${ROOT}.tar.gz`;
rm('-rf', ROOT);
mkdir('-p', ROOT);
定义要规定的目标列表
//以下以我官网源码为例
//https://github.com/ChangedenCZD/www.changeden.net/tree/v3
let targetList = [
'./bin',
'./build',
'./config',
'./routes',
'./src',
'./utils',
'./views',
'./*.js',
'./package.json'
];
创建计时器
//由于过程中过多异步的嵌套,不想用计数器,所以用一个计时器去控制执行下一步
let tickerId = null;
function resetTicker () {
if (tickerId) {
clearTimeout(tickerId);
}
tickerId = null;
}
function startTicker () {
resetTicker();
tickerId = setTimeout(() => {
startToCompress();
}, 10000); //延时10s,一般2s足够了,按需调整
}
定义文件复制方法
//用于复制目标到临时归档文件夹
function startToCopyFile () {
console.log('Start to copy file');
targetList.forEach((filePath) => {
//glob.sync('./*.*')会返回所有文件夹及文件,结果为一个字符串数组
//glob.sync('./*.js')会提取出当前文件夹中的所有js后缀文件,不包括子文件夹
//glob.sync('./**/*.js')会提取出当前文件夹中的所有js后缀文件,包括子文件夹
glob.sync(filePath).forEach((file) => {
let target = `${ROOT}/${file}`;
//复制文件到目标到临时归档文件夹
fs.copy(file, target, err => {
startTicker();
if (err) {
rm('-rf', target);
console.error(err);
} else {
console.log(`${file} had move.`);
}
});
});
});
}
定义压缩方法
//将临时归档文件夹压缩为归档文件
function startToCompress () {
console.log('Start to compress');
resetTicker();
targz().compress(ROOT, ROOT_TAR_GZ)
.then(function () {
console.log(`${ROOT} had compress.`);
startToSendFilesBySSH();
rm('-rf', ROOT);
})
.catch(function (err) {
console.error(err);
rm('-rf', ROOT);
});
}
定义部署到远程服务器的方法
let connect = new Client();
function startToSendFilesBySSH () {
console.log('Start to send files by SSH');
connect.on('ready', function () {
//获取sftp客户端,用于传输文件
connect.sftp(function (err, sftp) {
if (err) throw err;
//sftp.fastPut(本地要传输的文件路径,远程服务器的文件路径,额外选项,回调)
sftp.fastPut(ROOT_TAR_GZ, `/root/${ROOT_TAR_GZ}`, {}, (err) => {
if (err) {
console.error(err);
end();
} else {
console.log(`${ROOT_TAR_GZ} had send to remote server.`);
//定义项目最终文件路径
const TARGET = '/www.changeden.net';
//定义要在远程服务器执行的命令,如重启Tomcat等等
//解压 tar -xvf xxx.tar.gz
//覆盖旧项目 \cp -f xxx/* /www.changeden.net
//CentOs中的 \cp -f 用于忽略确认覆盖提示,Ubuntu 用 cp -rf
//重新编译运行 npm install && npm up -save && pm2 restart all
const shellText = `
cd /root && tar -xvf ${ROOT_TAR_GZ}
rm -f ${ROOT_TAR_GZ} && \\cp -f ${ROOT}/* ${TARGET}
rm -rf ${ROOT}
cd ${TARGET} && npm install && npm up -save && npm run fixAndMove
pm2 restart official
exit
`;
connect.shell((err, stream) => {
if (err) throw err;
stream.on('close', () => {
console.log('Finish.');
end();
}).on('data', (data) => {
console.log('Progress: ' + data);
}).stderr.on('data', (data) => {
console.log('Error: ' + data);
});
stream.end(shellText);
});
}
});
});
});
//创建SSH连接
connect.connect({
host: '远程服务器公网IP',
port: 22,
username: '远程服务器用户名',
password: '远程服务器登录密码',
readyTimeout: 60000
});
}
//关闭SSH连接
function end () {
connect.end();
}
要了解更多互联网技术,请关注我的头条号!
兔子人网:
https://www.changeden.net
我的Github:
https://github.com/ChangedenCZD
动态数据库使用教程:
https://bunnydb.changeden.net
与我联系:
changeden520@gmail.com
群:618839726
本文暂时没有评论,来添加一个吧(●'◡'●)