pm2:从小白到写出一键部署前后端工程

背景

基于公司KPI自我学习进步,以及我本人是负责后台管理系统开发维护的大环境背景下,我决定研究并开发了,拖拽生成代码的工具,目前完成的功能有: 拖拽生成 Table 页面和拖拽自动生成 Form 表单。

    1. 拖拽生成 Table 页面
    • 拖拽组件,从菜单栏到中间区域,或者同区域内更换位置,不同区域可以更换,只是目前,没有一个组件是会同时可以出现在 2 个区域的,所以此功能暂时无法看到;
    • 单击编辑属性
    • 右击删除
    • 生成代码
      • 可直接复制
      • 可生成文件并下载 zip 包
    1. 拖拽自动生成 Form 表单
      拖拽生成 form 表单,从左侧菜单栏中,将 form 元素拖到中间区域,可根据右上角的「N 列布局」输入你想要的 N 列布局,中间区域的各个 form 表单元素,可自由拖拽更换位置。可以点击这里来使用。此功能第一个版本可以看到的有:
    • 可以生成是单列,双列或者 N([1,10]) 列
    • 可以拖拽生成组件
    • 添加普通校验:必填
    • 单击编辑属性
    • 右击删除
    • 生成代码
      • 可直接复制
      • 可生成文件并下载 zip 包
    • 解决拖拽过程中定位不准确的 bug

简介

该项目前后端分离,前端是react写的,后端是node写的一个非常小的服务,用于生成目录文件,以及压缩zip包来下载生成的代码。写这个项目也主要是为了自己走一遍前端从开发到部署的所有流程。

本人主业是前端工程师,node是自己感兴趣想学的,所以写的只能说功能上还能用,代码质量渣的xx。

学习步骤

项目目录介绍


image.png

原始农业

刚开始,只为满足功能,能跑起来就OK。
纯手工部署。步骤如下:

前端部分

先登录服务器,将,代码git clone 下来,然后cd service目录下执行npm install

# 在本地项目执行命令
# 正确来说,应该在服务器上执行这个命令,鉴于我的阿里云服务器内存很小,就在本地执行。但是基于工作经历来说,我们有的线上项目,大型后,在线上服务器进行build也会很慢,有时候还会卡死,所以在本地build也没什么薄饼。
npm run build

# 拷贝(在本地执行)
# 服务器上的路径,/srv/front,直接将文件夹重命名为front
# 注意:一定要在该项目目录下进行
scp -r build root@ssh root@47.105.**.**:/srv

# 在服务器执行
# 登录服务器
ssh root@47.105.xxx.xxx
cd /srv/
# 删除旧的文件
rm -rf front/
# 重命名build为front
mv build front

后端部分

# 登录远程服务器
ssh root@47.105.xxx.xx

# 更新代码
cd /srv/bms-code-auto-generate
git pull origin master

# 远程启动后端,如果已经启动着,需要先关闭再重新启动
nohup node index.js &
# 关闭后端服务
ps aux | grep node
kill -9 pid

近代农业

等完成部署后,就发现这样每次都很麻烦,因为不想每次更新了代码,再去手动重启一遍node,这时候想起来了pm2,它可以在监控到文件更新后,去自动重启服务,所以就想着应用上pm2。

PM2 是一个守护进程管理器,它将帮助您管理和保持您的应用程序 24/7 在线。
nodejs的高级生产流程管理器。

也有其他解释:

而pm2是基于nodejs开发的进程管理器,适用于后台常驻脚本管理,同时对node网络应用有自建负载均衡功能。官方的说法,pm2 是一个带有负载均衡功能的Node应用的进程管理器,个人认为,并不准确,因为pm2支持多种语言,只是对于除node之外的其他进程无负载均衡的能力。 - 知乎

第一版 简单使用pm2 去启动index.js文件

在服务器上。

# 启动后端服务,pm2版本,
## 全局安装pm2
npm install -g pm2
## 改用pm2来启动程序--watch表示,监控程序运行状态,一旦:服务异常:自动重启;服务发生变化:自动重启
pm2 start index.js --watch

这样启动的node进程,有个问题,就是我的下载文件xxx.zip文件是保存在tmp目录下,每当我一点下载的时候,node进程就会重启。

image.png

重启的时候有时候会导致下载链接失败。


image.png

这是在请教做node的同学时的聊天截图继续,所以moduleName一个是cvb,下载的zip文件名确是666600.zip,有点对不上,因为不是同一个时间段的,是后来写文的时候翻看的聊天记录。

后来发现,去掉--watch不会重启,并且下载链接不会报错,但是,这时候,又出现了一个问题,就是,当代码有更新时,node服务并不会自动重新启动,这就又回到了“原始农业”时代,我觉得应该监控文件是可配置的,这时候发现,得去学习一下pm2啦,于是我去翻看了pm2的官方文档,找到了ignore_watchecosystem.config.js文件。

于是有了,在/service/目录下添加文件:ecosystem.config.js

image.png

将代码更新到服务上去后,可以使用命令pm2 start ./service/ecosystem.config.js 进行启动,这样启动的就比较方便了。

备注

pm2起的项目路径这样的:


image.png

在其中是会包含current和source的。我们需要手动,在source下,添加git仓库的地址,项目源码是在这里面的。

current -- 当前服务运行的文件夹(是source的软链接)
share -- log pid 等共享数据 (我目前的项目中没有这个文件)
source -- clone 下来的源代码
-- 简书友

现代农业

虽然上面的后端部署方式有了很大的改进,但是还是有个弊端就是,需要每次登陆服务器并且去手动拉代码,这样很麻烦。

于是写了一个一键部署的命令。

后端 v1.0

在原有的文件:ecosystem.config.js中进行扩展。

module.exports = {
    apps: [
        {
            name: 'generate',
            script: './index.js',
            // instances: 1,
            watch: true,
            ignore_watch: ['[/\\]./', 'node_modules', 'tmp']
        }
    ],
    deploy: {
        daily: {
            user: 'root',
            host: ['47.105.xx.xx'],
            ref: 'origin/node',
            repo: 'git@github.com:springHyc/bms-code-auto-generate.git',
            path: '/srv/hehe/bms-code-auto-generate3',
            'post-deploy': 'git pull && cd service &&   npm install && npm run daily',
            env: {
                NODE_ENV: 'daily'
            }
        }
    }
};

配合package.json中添加命令:

"scripts": {
        "daily": "NODE_ENV=daily  pm2 startOrRestart ecosystem.config.js"
    },

这样直接在本地运行:pm2 deploy ./service/ecosystem.config.js daily,即可完成,自动拉取最新的代码,并且完成重启目的。

在第一次执行前,应该进入目录/srv/hehe/bms-code-auto-generate3中,手动新建mkdir source这个文件夹,不然后报错。

image.png

然后还要将/srv/hehe/bms-code-auto-generate3目录下clone项目git clone origin git@github.com:***c/bms-code-auto-generate.git,再将项目名称更改为source

后端 v2.0

上面的方式,仍然不太好,因为在本地运行的时候,ecosystem.config.js文件是放在./service/目录下的,我们能不能将ecosystem.config.js文件放在根目录下呢?继续研究试验...

在根目录下新建ecosystem.config.js文件:

// 在v1.0版本和v2.0版本中,我们将命令的名字做了更改。
module.exports = {
    apps: [
        {
            name: 'node-generate',
            script: './index.js',
            cwd: './service/',
            watch: false,
            log_date_format: 'YYYY-MM-DD HH:mm Z'
        }
    ],
    deploy: {
        daily: {
            user: 'root',
            host: ['47.105.**.**'],
            ref: 'origin/node',
            repo: 'git@github.com:springHyc/bms-code-auto-generate.git',
            path: '/srv/hehe/bms-code-auto-generate3',
            'post-deploy': 'git pull && cd service && npm install && cd ../ && npm run deploy-node',
            env: {
                NODE_ENV: 'daily'
            }
        }
    }
};

配合package.json中添加命令:

"deploy-node": "NODE_ENV=daily pm2 startOrRestart ecosystem.config.js",
"deploy-end": "pm2 deploy ecosystem.config.js daily",

这样在本机根目录下执行npm run deploy-end即可完成,自动拉取最新的代码,并且完成重新部署的目的。

前端

至于前端代码,我们没有做build相关的优化,所以前端代码的打包很简单,只需要build,然后将build出来的build/目录拷贝到服务器的某个位置,like: /srv/hehe/bms-code-auto-generate3/build,然后配置好ngnix代理即可。

手动部署的命令是:

# 在本地项目执行命令
# 正确来说,应该在服务器上执行这个命令,鉴于我的阿里云服务器内存很小,就在本地执行。但是基于工作经历来说,我们有的线上项目,大型后,在线上服务器进行build也会很慢,有时候还会卡死,所以在本地build也没什么薄饼。
npm run build

# 拷贝(在本地执行)
# 服务器上的路径,/srv/front,直接将文件夹重命名为front
# 注意:一定要在该项目目录下进行
scp -r build root@ssh root@47.105.**.**:/srv/hehe/bms-code-auto-generate3

那我们能不能写个命令让它自动执行呢?可以啊

就是这个,在package.json中添加命令:

"deploy-front": "npm run build && scp -r build root@47.105.**.**:/srv/hehe/bms-code-auto-generate3",

那现在我们执行npm run deploy-front就可以部署前端啦。

那现在有想了,我们可不可以把前后端部署命令合并成一个命令呢?分开都麻烦啊☹️

于是就有了这个命令,在package.json中添加命令:

"deploy": "npm run deploy-end && npm run deploy-front"
现在我们执行npm run deploy就可以自动部署前后端啦。


前端部署还有一种方式,是直接在服务器上build的,由于我们有内部包的限制,外网无法访问通,所以上面我一直采用的是本地build的方式。

服务器上build方式为:

// ecosystem.config.js文件中添加
deploy: {
        daily2: {
            user: 'root',
            host: ['47.105.**.**'],
            ref: 'origin/node',
            repo: 'git@github.com:springHyc/bms-code-auto-generate.git',
            path: '/srv/hehe/bms-code-auto-generate3',
            'post-deploy': 'git pull && npm i --registry=http://shuqudata.registry.com && npm run build',
            env: {
                NODE_ENV: 'daily2'
            }
        }
    }
// package.json中添加
 "deploy-front-remote": "pm2 deploy ecosystem.config.js daily2",

然后执行npm run deploy-front-remote即可。
这个地方注意,build后,build文件路径在/source/根目录下,要进行nginx配置才可以访问。

备注

为什么我会把项目/srv/hehe/bms-code-auto-generate3放在这个目录上呢,因为这是个从无到有的尝试过程,我原本在/srv/是手动起着一套前后端的,我不想破坏正在启动着的应用。

  • 服务上ngnix配置
# 路径:/etc/nginx/sites-enabled/
# 文件名:hehe-bms (其实是随便起的,只是为了试验)
server {
        listen       8080;
        server_name  47.105.**.**;

    location /api {
            proxy_pass  http://localhost:3003; // 后端地址
        }

    location / {
        root /srv/hehe/bms-code-auto-generate3/build/; // 前端路径
        index index.html index.htm;
            try_files $uri $uri/ /index.html;
        }
}

注意,nginx配置修改后,一定要重启nginx,不然不生效。重启命令nginx -s rolad,想要学习有关nginx的命令请看我的总结

  • ecosystem.config.js
module.exports = {
    apps: [
        {
            name: 'node-generate',
            script: './index.js',
            cwd: './service/',
            watch: false,
            log_date_format: 'YYYY-MM-DD HH:mm Z'
        }
    ],
    deploy: {
        daily: {
            user: 'root',
            host: ['47.105.**.**'],
            ref: 'origin/node',
            repo: 'git@github.com:springHyc/bms-code-auto-generate.git',
            path: '/srv/hehe/bms-code-auto-generate3',
            'post-deploy': 'git pull && cd service && npm install && cd ../ && npm run deploy-node',
            env: {
                NODE_ENV: 'daily'
            }
        }
    }
};

  • package.json
{
    "name": "bms-code-auto-generate",
    "version": "0.2.0-alpha0.1",
    "private": true,
    "scripts": {
        "dev": "node scripts/start.js",
        "build": "node scripts/build.js",
        "test": "node scripts/test.js",
        "deploy-node": "NODE_ENV=daily pm2 startOrRestart ecosystem.config.js",
        "deploy-end": "pm2 deploy ecosystem.config.js daily",
        "deploy-front": "npm run build && scp -r build root@47.105.**.**:/srv/hehe/bms-code-auto-generate3",
        "deploy": "npm run deploy-end && npm run deploy-front"
    },
...
}
  • pm2 命令
命令 含义
pm2 stop id/name 暂停
ps aux | grep node 查看node进程
pm2 list 查看pm2启动列表
pm2 start index2.js --watch 启动项目
pm2 logs 查看日志
pm2 restart app_name 杀死并重新启动进程。restart = stop+start
pm2 reload app_name reload实现了0秒的停机时间重新加载.reload = 重新读取配置文件
pm2 stop app_name
pm2 delete app_name
pm2 flush | pm2 flush <api> 清空 PM2 管理的当前应用程序日志
pm2 monit 监控CPU/内存
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,240评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,328评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,182评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,121评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,135评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,093评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,013评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,854评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,295评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,513评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,398评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,989评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,636评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,657评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容