• gulp自动化部署:gulp发布express项目(二)


    原文:https://my.oschina.net/songzhu/blog/610337

    一、服务器准备

        服务器ip地址为:172.16.70.174

        1.安装 Node.js

        参考:http://my.oschina.net/songzhu/blog/608129

        2.安装 PM2

        PM2 是一个带有负载均衡功能的 Node 应用的进程管理器。

        全局安装 PM2

    $ 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 如果出现错误,大概是网络和权限问题导致的。仔细看一下错误提示,如果是网络问题,那么多重试几次应该就可以了。

        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

     

    二、创建 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/

    三、创建 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

     

        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: ' ',
                             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上传文件时会出错。

    四、一键部署 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/

    项目代码:https://git.oschina.net/cavintang/express-demo.git

  • 相关阅读:
    30.过滤掉smb.conf配置文件中的空行和注释行和空白行(初级写法很不严谨)
    29. 分析文件内容,判断 fgets 共执行了多少次?
    28. 使用fgetc()/fputc()实现文件的加密与解密,存在溢出风险。
    27.读文件时通过两种方式判断文件结尾
    26. 使用fgetc()/fputc()实现文件的拷贝
    24. 练习定义几种指针及数组
    23. 实现 func()函数,在func()中,通过操作arr,实现修改str1到str2字符串,并打印所有字符串,考察对指针与数组与字符串的基本掌握
    Windows程序设计(Charles Petzold)HELLOWIN程序实现
    jvm 解释器和JIT编译器
    java 创建线程的方法
  • 原文地址:https://www.cnblogs.com/zzcit/p/7526335.html
Copyright © 2020-2023  润新知