基于node-scp2的自动化部署方式
基于node-scp2方式的自动化部署,只需要在创建项目阶段配置好前三个步骤,之后每次上传文件至服务器时只需要最后一步:执行步骤三注册的命令即可。
什么是scp2
一个基于 ssh 的纯 JavaScript 安全复制程序。
优点
可以在每个操作系统上执行,unix、Linux、windows等。
注意
在windows上执行需要依托Node环境,最低版本为 v0.8.7。
第一步:使用 vue-cli 创建自己项目并进入
vue create auto-deployment cd auto-deployment第二步:安装scp2模块
npm install scp2 --save-dev第三步:创建服务器配置文件
在根目录下创建deploy文件夹, 在 deploy 文件夹下创建 config.js文件用来保存服务器的配置信息。
server: { id: 'server1', // 服务器配置id - 随意,目的是便于代码理解 name: '测试环境', // 当前项的配置名 - 随意,目的是对服务器配置的解释 host: '10.xx.xx.xx', // 服务器IP port: 22, // 服务器端口,默认为22,一般情况下都是22 username: 'root', // 服务器登录名 - 登录xshell时的用户名 password: 'user*****', // 服务器登录密码 - 登录xshell时的密码 path: '/home/user/test/test1' // 文件上传到服务器的路径 },第四步:使用scp2库,创建自动化部署脚本
在 deploy文件下创建index.js文件,用于存放自动化部署脚本
// 引入scp2库 const scpClient = require('scp2'); // node模块 - node.js 命令行环境的 loading效果和显示各种状态的图标 const ora = require('ora'); // node模块 - node终端样式库 const chalk = require('chalk'); // 服务器配置 const server = require('./config')[( process.env.NODE_ENV === 'prod' ? 'prod' : 'dev')]; // node 终端提示语,process.env:当前进程环境 const spinner = ora('正在发布到' + ( process.env.NODE_ENV === 'prod' ? '生产' : '测试') + '服务器...'); // loading spinner.start(); // 执行scp2库,上传文件 // 第一个参数:要上传到服务器的文件 // 第二个参数:服务器配置 // 第三个参数:上传回调函数 scpClient.scp( './dist/', { host: server.host, port: server.port, username: server.username, password: server.password, path: server.path }, function (err) { spinner.stop(); if (err) { console.log(chalk.red('发布失败.\n')); throw err; } else { console.log(chalk.green('Success! 成功发布到' + (process.env.NODE_ENV === 'prod' ? '生产' : '测试') + '服务器! \n')); } } );第五步:添加执行命令
在 package.json中注册执行命令,自定义命令名称:
"scripts": { "serve": "vue-cli-service serve --mode dev", "build": "vue-cli-service build --mode prod", "deploy": "cross-env NODE_ENV=prod node ./deploy" },注意:cross-env 用于设置当前环境变量,在使用 cross-env 前,要先使用 npm install cross-env 安装该模块。如果不设置环境变量或者不使用环境变量,可以注册 deploy 命令为:
"scripts": { "serve": "vue-cli-service serve --mode dev", "build": "vue-cli-service build --mode prod", "deploy": "node ./deploy" },第六步:在 terminal 中输入命令,上传文件到服务器中
在控制台输入以下命令,当控制台提示 ’Success! 成功发布到10.xx.xx.xx服务器! ‘时,表示文件上传成功,此时登录服务器可查看已上传文件。
npm run deploy以上六个步骤,实现了一个基础的自动化部署方案,需要 尤其,特别,极其 的注意以下几个方面:
服务器配置的路径是很重要的,表示要将dist文件夹下的文件上传到该文件夹下,在第一次上传前最好使用测试文件夹测试一下。以上步骤中的文件夹名、文件名、命令名都是自定义,可以随意修改最最最重要的一点:在上传git时一定要将服务器配置文件添加到 .ignore文件中优化版本并不是指比基础版性能更好,而是在基础版本上新增了其他功能,日常开发中按开发需求使用不同版本。
区分多环境部署,即在配置文件中配置好不同环境服务器,在执行命令时通过不同的部署命令来区分部署到哪台服务器上。(在日常开发中一般我们用不到)
配置文件
const SERVER_CONFIG = { dev: { id: 'dev', name: '测试环境', host: '10.xx.xx.xx', port: 22, username: 'root', password: 'user******', path: '/root/user/test/dev/', // 上传文件的路径 - 包括文件名 rootPath:'/root/user/test/', // 上传文件的根路径 rootFolder:"dev", // 上传文件的文件名 }, prod: { id: 'prod', name: '生产环境', host: '10.xx.xx.xx', port: 22, username: 'root', password: 'user******', path: '/root/user/test/prod/', rootPath:'/root/user/test/', rootFolder:"prod", } }; module.exports = SERVER_CONFIG;强烈推荐至少要使用该版本,在上传文件前对旧版文件进行备份,方便版本回退或部署失败后能够保证生产环境能够正常运行。
在基础版本上对 第四步 - 创建自动化部署脚本时进行了修改,在上传文件前,使用 ssh 先对原文件进行拷贝,删除,之后再上传文件。
基本实现思路如下:
进入到上传文件的根目录下 - 即 server配置中的 rootPath属性新建一个文件夹用于备份 _backUp/文件名拷贝旧版部署包到备份文件夹下删除旧版部署包上传新版部署包具体实现方案:
导入 ssh2 模块
// ssh2 传输 const Client = require('ssh2').Client; const conn = new Client();声明要执行的命令:
let cmd = `cd ${rootPath}\n mkdir -p _backUp/${rootFolder}_${currentTime}\n cp -r ${path} ${rootPath}_backUp/${rootFolder}_${currentTime}/\n rm -rf ${path}`;连接服务器,执行命令:
conn.on('ready',function(){} .on('error',function(){}) . .connect({ host: server.host, port: server.port, username: server.username, password: server.password });完整版配置:
// 以下配置同基础版 const scpClient = require('scp2'); const ora = require('ora'); const chalk = require('chalk'); const server = require('./config')[( process.env.NODE_ENV === 'prod' ? 'prod' : 'dev')]; const spinner = ora('正在发布到' + ( process.env.NODE_ENV === 'prod' ? '生产' : '测试') + '服务器上...'); // ssh2 传输 const Client = require('ssh2').Client; const conn = new Client(); function deployFile() { let { path , rootPath , rootFolder } = server ; let currentTime = new Date().toLocaleDateString(); // 执行的命令 let cmd = `cd ${rootPath}\n mkdir -p _backUp/${rootFolder}_${currentTime}\n cp -r ${path} ${rootPath}_backUp/${rootFolder}_${currentTime}/\n rm -rf ${path}`; conn.on('ready', function () { conn.exec( cmd, function (err, stream) { console.log(chalk.green('已执行命令行')); console.log(chalk.yellow(cmd)); if (err) throw err; // 在执行命令行成功后上传文件到服务器上 stream.on('close', function (code, signal) { spinner.start(); scpClient.scp( './dist/', { host: server.host, port: server.port, username: server.username, password: server.password, path: server.path }, function (err) { spinner.stop(); if (err) { console.log(chalk.red('Fail! 发布失败.\n')); throw err; } else { console.log(chalk.green('Success! 成功发布到' + server.host + '服务器! \n')); } } ); conn.end(); }) }); }) .on('error', function (err) { console.log(chalk.red('Fail! 服务器连接失败.\n')); throw err; }) .connect({ host: server.host, port: server.port, username: server.username, password: server.password }); }交互型输入用户名和密码,指为了保密性不将服务器的用户名和密码直接明文写死在配置中,而是在上传文件时交互式的输入用户名和密码,
基本实现思路如下:
使用node-readline模块支持输入用户名和密码获取到用户名和密码后动态赋值给server对象通过赋值后的server对象连接服务器,从而达到自动化部署具体实现方案:
导入readline模块:
const readline = require('readline');创建readline实例:
const rl = readline.createInterface({ input: process.stdin, output: process.stdout })设置问题提问:
const questions = ['Please input publish environment(dev\\prod\\): ', 'Please input server username: ', 'Please input server password: '] const linelimit = 3; // 用户输入的行数 let inputArr = []; let index = 0; let server = null; function runQueLoop() { if (index === linelimit) { server = config[inputArr[0]] // 通过输入内容匹配当前环境 server.username = inputArr[1]; // 通过输入内容来匹配用户名 server.password = inputArr[2]; // 通过输入内容匹配密码 deployFile(); // 执行上一步中的上传操作 return; } rl.question(questions[index], (as) => { inputArr[index] = as; index++; runQueLoop() }) }基础版完整实现代码
https://github.com/jianyaoo/Front-end-demo/tree/master/Vue%E6%A1%86%E6%9E%B6/auto-deployment/deploy_advance
优化版2 - 上传前备份版完整实现代码
https://github.com/jianyaoo/Front-end-demo/tree/master/Vue%E6%A1%86%E6%9E%B6/auto-deployment/deploy_advance
优化版3 - 交互型输入完整实现代码
https://github.com/jianyaoo/Front-end-demo/tree/master/Vue%E6%A1%86%E6%9E%B6/auto-deployment/deploy_readline