原文:https://my.oschina.net/songzhu/blog/610337php
1、服務器準備node
服務器ip地址爲:172.16.70.174git
1.安裝 Node.jsweb
參考:http://my.oschina.net/songzhu/blog/608129shell
2.安裝 PM2express
PM2 是一個帶有負載均衡功能的 Node 應用的進程管理器。npm
全局安裝 PM2json
$ npm install pm2 -g $ pm2 list [PM2] Spawning PM2 daemon [PM2] PM2 Successfully daemonized ┌──────────┬────┬──────┬─────┬────────┬─────────┬────────┬────────┬──────────┐ │ App name │ id │ mode │ pid │ status │ restart │ uptime │ memory │ watching │ └──────────┴────┴──────┴─────┴────────┴─────────┴────────┴────────┴──────────┘ Use `pm2 show <id|name>` to get more details about an app
安裝 PM2 若是出現錯誤,大概是網絡和權限問題致使的。仔細看一下錯誤提示,若是是網絡問題,那麼多重試幾回應該就能夠了。gulp
3.準備發佈目錄 瀏覽器
/home/admin/publish/web/express-demo
$ cd ~ $ mkdir publish && cd publish $ mkdir web && cd web $ mkdir express-demo && cd express-demo $ pwd /home/admin/publish/web/express-demo
2、建立 PM2 啓動腳本
進入 express-demo 目錄,添加文件 pm2-start.json
$ touch pm2-start.json
添加如下內容:
[ { "name" : "express-demo", "script" : "./app.js", "watch" : false, "instances" : "4", "exec_mode" : "cluster_mode", "env": { "NODE_ENV": "production" }, "out_file": "./logs/app.log", "error_file": "./logs/err.log", } ]
經過 pm2 start pm2-start.json,可啓動 express-demo。
更詳細的配置:http://pm2.keymetrics.io/docs/usage/application-declaration/
3、建立 Gulp 任務
Gulp 用自動化構建工具加強你的工做流程。
1.全局安裝 gulp
$ npm install gulp -g $ gulp -v [23:57:39] CLI version 3.9.0
2.做爲項目的開發依賴安裝 gulp
$ npm install --save-dev gulp $ gulp -v [23:58:00] CLI version 3.9.0 [23:58:00] Local version 3.9.0
3.在項目根目錄建立 gulpfile.js
$ touch gulpfile.js $ gulp [23:57:01] Using gulpfile ~/demos/express-demo/gulpfile.js [23:57:02] Task 'default' is not in your gulpfile [23:57:02] Please check the documentation for proper gulpfile formatting
看到錯誤是由於我沒尚未在 gulpfile.js裏面添加內容
4.添加 gulp 部署依賴
$ npm install --save-dev gulp-util gulp-shell gulp-ssh gulp-zip through2 scp2 async progress
5.在項目根目錄建立 deploy-ssh.js
$ touch deploy-ssh.js
添加如下內容:
var gulp = require('gulp'); var gutil = require('gulp-util'); var through = require('through2'); var ScpClient = require('scp2').Client; var ssh = require('gulp-ssh'); var async = require('async'); var ProgressBar = require('progress'); const PLUGIN_NAME = 'deploy-ssh' module.exports = function (options) { var servers = options.servers; var dest = options.dest; var shell = options.shell; var logPath = options.logPath; return through.obj(function (file, enc, callback) { if (file.isNull()) { callback(null, file); return; } if (file.isStream()) { return callback(new gutil.PluginError(PLUGIN_NAME, 'No stream support')); } var i = 0; async.eachSeries(servers, function(server, done) { var hostName = server.sshConfig.host; gutil.log(PLUGIN_NAME, "start deploy:" + hostName) var client = new ScpClient(server.sshConfig); var bar = null; client.on("transfer", function(buffer, uploaded, total){ if(bar == null){ bar = new ProgressBar(hostName + ' uploading [:bar] :percent :elapsed s', { complete: '=', incomplete: ' ', width: 50, total: total }); } bar.tick(1); }); client.write({ destination: dest, content: file.contents }, function () { ssh(server).shell(shell, {filePath: logPath + "-" + hostName + ".log", autoExit: true}).on('error', function (err) { done(err); gutil.PluginError(PLUGIN_NAME, err) }).on('finish', function () { gutil.log(PLUGIN_NAME, "finish deploy:" + hostName); done(); if (++i === servers.length) { callback(null, file); } }).pipe(gulp.dest('logs')); }); }); }); };
deploy-ssh 主要用於上傳發布包至服務器並登陸服務器之行發佈腳本。
6.在項目根目錄建立 deploy-config.js
$ touch deploy-config.js
添加如下內容:
var config = { production:{ servers:[ { sshConfig: { host: '172.16.70.174', port: 22, username: 'admin', password: 'cavin@123', readyTimeout: 200000 } }] } }; module.exports = config;
deploy-config 主要用於配置deploy服務器信息。
7.修改 gulpfile.js
添加如下內容:
var gulp = require('gulp'); var shell = require('gulp-shell'); var ssh = require('gulp-ssh'); var deployConfig = require("./deploy-config"); var gulpSequence = require('gulp-sequence'); var zip = require('gulp-zip'); var through = require('through2'); var async = require('async'); var scpClient = require('scp2'); var gulpUtil = require('gulp-util'); var deploySSH = require('./deploy-ssh'); const PLUGIN_NAME = 'gulp-deploy ::' gulp.task('default', shell.task([ 'DEBUG=express-demo:* npm start' ])); gulp.task('production', function (){ shell.task(['rm -rf dist']); gulpSequence('copyFile', 'zipFile', 'deploy', function() { gulpUtil.log(PLUGIN_NAME, "***** Deploy Finished!!!!"); process.exit(0); }); }); gulp.task('copyFile', function() { return gulp.src( [ '*.json', '*.js', 'routes/**', 'views/**', 'public/**', '!config.js' ], { base: './'}) .pipe(gulp.dest('./dist')); }); gulp.task('zipFile', function() { return gulp.src(['dist/**'], { base: './' }) .pipe(zip('publish.zip')) .pipe(gulp.dest('./dist')); }); gulp.task('deploy', function() { var config = deployConfig.production; config.deployPath = '/home/admin/publish/web/express-demo/'; return gulp.src("dist/publish.zip", { base: './' }) .pipe(deploySSH({ servers: config.servers, dest: config.deployPath + 'publish.zip', logPath: 'deploy', shell:[ 'cd ' + config.deployPath, 'shopt -s extglob', 'rm -rf !(logs|node_modules|config.js|publish.zip)', 'unzip -o publish.zip', 'cp -rf dist/** .', 'rm -rf dist', "rm publish.zip", 'npm install --production', 'pm2 startOrRestart pm2-start.json'], })); });
主要 gulp 任務流程爲:
1)拷貝文檔至臨時目錄
2)壓縮文件
3)發佈(先上發佈包,而後遠程登陸服務器之行發佈腳本)
注:發佈目錄 '/home/admin/publish/web/express-demo/' 必定要存在,不然scp上傳文件時會出錯。
4、一鍵部署 express-demo
執行發佈任務
$ gulp production
若是沒有錯誤,登陸服務器上面能夠看到:
$ pm2 list ┌──────────────┬────┬─────────┬──────┬────────┬─────────┬────────┬─────────────┬──────────┐ │ App name │ id │ mode │ pid │ status │ restart │ uptime │ memory │ watching │ ├──────────────┼────┼─────────┼──────┼────────┼─────────┼────────┼─────────────┼──────────┤ │ express-demo │ 0 │ cluster │ 2537 │ online │ 0 │ 102s │ 30.117 MB │ disabled │ │ express-demo │ 1 │ cluster │ 2542 │ online │ 0 │ 102s │ 30.133 MB │ disabled │ │ express-demo │ 2 │ cluster │ 2543 │ online │ 0 │ 102s │ 30.109 MB │ disabled │ │ express-demo │ 3 │ cluster │ 2544 │ online │ 0 │ 102s │ 30.363 MB │ disabled │ └──────────────┴────┴─────────┴──────┴────────┴─────────┴────────┴─────────────┴──────────┘ Use `pm2 show <id|name>` to get more details about an app
在瀏覽器裏面輸入:http://172.16.70.174:3000/