• 对于注定会优秀的人来说,他所需要的,只是时间----博主
  • 手懒得,必受贫穷,手勤的,必得富足----《圣经》
  • 帮助别人,成就自己。愿君在本站能真正有所收获!
  • 如果你在本站中发现任何问题,欢迎留言指正!
  • 本站开启了防爆破关小黑屋机制,如果您是正常登录但被关进小黑屋,请联系站长解除!

<十七>Jenkins实战应用–Jenkins构建nodejs项目

Jenkins eryajf 7个月前 (05-23) 35°C 已收录 7个评论
本文预计阅读时间 34 分钟

*系列汇总*

这是一个系列文章,大大小小到今天惊然发现竟然已经累计二十篇了,也就不得不做一个小汇总。回想当初写第一篇文章的时候,就已经决心事无巨细,一应认真的走下来,回头遮望,看着皇皇这么多文章,一股强烈的成就感就此油然而生,于是便有了这些汇总整理。在这个过程当中,好像也帮助过不少的人,这是让我尤其开心的事情,同时也结识了一些志同道合的朋友,再没有比这更让人觉得愉悦的事情啦!也希望以后写出更多类似的系列文章。

文章汇总地址如右:Jenkins 入门教程。

如果相中哪个,点击进去便是。希望正在读这段话的你能够在这个小系列中获得自信以及喜悦!

之前自己好像在一个项目的构建当中说过这样的话,“而如果是其他的诸如前端啊,PHP 之类的项目,则就更简单了”,说出去之后好像这些项目的构建操作真的非常简单一般的,也就没有在对此进行任何表述。

但是有不少公司其实是纯 web 端服务的,这个时候构建前端项目则显得成为一个主要的事儿了,那么究竟该如何来构建一个完整前端项目呢?

今天我就借以 nodejs 项目举例,不仅仅把 node 项目完整配置流程讲清楚,更借此机会把如何利用 git 分支的办法进行项目的回滚之操作给表述一下,这次表述是一个引子,以后或许会专门写一篇关于回滚的文章吧。

首先说 nodejs 是一个跑起来的服务,需要一些依赖,而每个开发所定义的或者使用的命令之类的又不一样,因此在做 nodejs 的准备工作的时候就很有必要与开发者结合着来做。

接下来进入正题,我们先来在 Jenkins 上做一些配置,先把代码给搞到目标服务器去。

首先创建一个新的项目 test-node。

进入到项目的配置里,添加两项参数。

注意,此处定义了一个名为 mode 的变量,到时候就通过这个变量的传递来实现整个流程是部署,还是回滚,或者是纯粹的项目重启一下。

字符参数定义发布代码的分支。

源码管理依旧使用 git 的地址。

在构建这里先简单写几条命令,让新鲜的代码推到远程服务器去。注意,这里所写的并不是最终脚本哦。因此也就不贴出来了。

然后执行一下构建先:

真的是超级简陋的,刚刚开始,什么都没有呢。

好了,现在去远程服务器上做一下环境的准备工作。

1,安装 node。

来波小小的操作。

cd /opt
wget https://nodejs.org/dist/v6.10.1/node-v6.10.1-linux-x64.tar.xz		#下载源码包
tar xf node-v6.10.1-linux-x64.tar.gz
mv /opt/node-v6.10.1-linux-x64 /urs/local/node	
ln -s /usr/local/node/bin/* /usr/local/bin/		

#做软链接让命令可用,也可以写入到/etc/profile 里,如果写入配置,那么内容如下:
export NODE_HOME=/usr/local/node
export PATH=$NODE_HOME/bin:$PATH
export NODE_PATH=$NODE_HOME/lib/node_modules:$PATH

node -v		#验证安装是否成功。

然后去到刚才同步过来的目录当中。也就是 node 项目的根目录中。

2,配置 node 的一些工具。

确保此时是在项目根目录下。

[root@localhost h5-node]# pwd
/usr/local/h5-node

然后安装项目中的依赖。

[root@localhost h5-node]# npm install --registry=https://registry.npm.taobao.org

这一步的操作因为我也不十分明白其中意义,百度一下还真有雷同的问题:https://segmentfault.com/q/1010000012142031

其实上边这一步是安装好本项目所有的依赖。

因为我这里的项目开发者用的是 gulp 进行管理的。因此来安装一下 gulp 与 pm2(每次看到这个词儿就想到开发大哥操着小口音说“嘎破”的样子)命令。

[root@localhost h5-node]# npm i -g gulp
[root@localhost h5-node]# npm i -g pm2

其中 i 是 install,-g 表示全局安装的意思。这两条命令安装都比较慢,请耐心等待。

成功的样子如下边:

[root@localhost h5-node]# npm i  pm2 -g
[    ..............] - fetchMetadata: sill mapToRegistry uri https://registry.npmjs.org/yamljs
npm ERR! fetch failed https://tgz.pm2.io/gkt-1.0.0.tgz
npm WARN retry will retry, error on last attempt: Error: connect ETIMEDOUT 163.172.101.189:443
npm ERR! fetch failed https://tgz.pm2.io/gkt-1.0.0.tgz
npm WARN retry will retry, error on last attempt: Error: connect ETIMEDOUT 163.172.101.189:443
npm ERR! fetch failed https://tgz.pm2.io/gkt-1.0.0.tgz
/usr/local/node/bin/pm2 -> /usr/local/node/lib/node_modules/pm2/bin/pm2
/usr/local/node/bin/pm2-dev -> /usr/local/node/lib/node_modules/pm2/bin/pm2-dev
/usr/local/node/bin/pm2-docker -> /usr/local/node/lib/node_modules/pm2/bin/pm2-docker
/usr/local/node/bin/pm2-runtime -> /usr/local/node/lib/node_modules/pm2/bin/pm2-runtime
/usr/local/node/lib
└─┬ pm2@2.10.4
  ├─┬ async@2.6.1
  │ └── lodash@4.17.10
  ├── blessed@0.1.81
  ├─┬ chalk@1.1.3
  │ ├── ansi-styles@2.2.1
  │ ├── escape-string-regexp@1.0.5
  │ ├─┬ has-ansi@2.0.0
  │ │ └── ansi-regex@2.1.1
  │ ├── strip-ansi@3.0.1
  │ └── supports-color@2.0.0
  ├─┬ chokidar@2.0.3
  │ ├─┬ anymatch@2.0.0
  │ │ └─┬ micromatch@3.1.10
  │ │   ├── arr-diff@4.0.0
  │ │   ├─┬ define-property@2.0.2
  │ │   │ └─┬ is-descriptor@1.0.2
  │ │   │   ├── is-accessor-descriptor@1.0.0
  │ │   │   └── is-data-descriptor@1.0.0
  │ │   ├─┬ extend-shallow@3.0.2
  │ │   │ ├── assign-symbols@1.0.0
  │ │   │ └─┬ is-extendable@1.0.1
  │ │   │   └── is-plain-object@2.0.4
  │ │   ├─┬ extglob@2.0.4
  │ │   │ ├─┬ define-property@1.0.0
  │ │   │ │ └─┬ is-descriptor@1.0.2
  │ │   │ │   ├── is-accessor-descriptor@1.0.0
  │ │   │ │   └── is-data-descriptor@1.0.0
  │ │   │ ├─┬ expand-brackets@2.1.4
  │ │   │ │ ├── debug@2.6.9
  │ │   │ │ ├── define-property@0.2.5
  │ │   │ │ ├── extend-shallow@2.0.1
  │ │   │ │ └── posix-character-classes@0.1.1
  │ │   │ └── extend-shallow@2.0.1
  │ │   ├── fragment-cache@0.2.1
  │ │   ├── kind-of@6.0.2
  │ │   ├─┬ nanomatch@1.2.9
  │ │   │ ├─┬ is-odd@2.0.0
  │ │   │ │ └── is-number@4.0.0
  │ │   │ └── is-windows@1.0.2
  │ │   ├── object.pick@1.3.0
  │ │   └── regex-not@1.0.2
  │ ├── async-each@1.0.1
  │ ├─┬ braces@2.3.2
  │ │ ├── arr-flatten@1.1.0
  │ │ ├── array-unique@0.3.2
  │ │ ├─┬ extend-shallow@2.0.1
  │ │ │ └── is-extendable@0.1.1
  │ │ ├─┬ fill-range@4.0.0
  │ │ │ ├── extend-shallow@2.0.1
  │ │ │ ├─┬ is-number@3.0.0
  │ │ │ │ └─┬ kind-of@3.2.2
  │ │ │ │   └── is-buffer@1.1.6
  │ │ │ ├── repeat-string@1.6.1
  │ │ │ └── to-regex-range@2.1.1
  │ │ ├── isobject@3.0.1
  │ │ ├── repeat-element@1.1.2
  │ │ ├─┬ snapdragon@0.8.2
  │ │ │ ├─┬ base@0.11.2
  │ │ │ │ ├─┬ cache-base@1.0.1
  │ │ │ │ │ ├─┬ collection-visit@1.0.0
  │ │ │ │ │ │ ├── map-visit@1.0.0
  │ │ │ │ │ │ └── object-visit@1.0.1
  │ │ │ │ │ ├── get-value@2.0.6
  │ │ │ │ │ ├─┬ has-value@1.0.0
  │ │ │ │ │ │ └─┬ has-values@1.0.0
  │ │ │ │ │ │   └── kind-of@4.0.0
  │ │ │ │ │ ├─┬ set-value@2.0.0
  │ │ │ │ │ │ └── extend-shallow@2.0.1
  │ │ │ │ │ ├─┬ to-object-path@0.3.0
  │ │ │ │ │ │ └── kind-of@3.2.2
  │ │ │ │ │ ├─┬ union-value@1.0.0
  │ │ │ │ │ │ └─┬ set-value@0.4.3
  │ │ │ │ │ │   └── extend-shallow@2.0.1
  │ │ │ │ │ └─┬ unset-value@1.0.0
  │ │ │ │ │   └─┬ has-value@0.3.1
  │ │ │ │ │     ├── has-values@0.1.4
  │ │ │ │ │     └── isobject@2.1.0
  │ │ │ │ ├─┬ class-utils@0.3.6
  │ │ │ │ │ ├── arr-union@3.1.0
  │ │ │ │ │ ├── define-property@0.2.5
  │ │ │ │ │ └─┬ static-extend@0.1.2
  │ │ │ │ │   ├── define-property@0.2.5
  │ │ │ │ │   └─┬ object-copy@0.1.0
  │ │ │ │ │     ├── copy-descriptor@0.1.1
  │ │ │ │ │     ├── define-property@0.2.5
  │ │ │ │ │     └── kind-of@3.2.2
  │ │ │ │ ├── component-emitter@1.2.1
  │ │ │ │ ├─┬ define-property@1.0.0
  │ │ │ │ │ └─┬ is-descriptor@1.0.2
  │ │ │ │ │   ├── is-accessor-descriptor@1.0.0
  │ │ │ │ │   └── is-data-descriptor@1.0.0
  │ │ │ │ ├─┬ mixin-deep@1.3.1
  │ │ │ │ │ ├── for-in@1.0.2
  │ │ │ │ │ └── is-extendable@1.0.1
  │ │ │ │ └── pascalcase@0.1.1
  │ │ │ ├── debug@2.6.9
  │ │ │ ├─┬ define-property@0.2.5
  │ │ │ │ └─┬ is-descriptor@0.1.6
  │ │ │ │   ├─┬ is-accessor-descriptor@0.1.6
  │ │ │ │   │ └── kind-of@3.2.2
  │ │ │ │   ├─┬ is-data-descriptor@0.1.4
  │ │ │ │   │ └── kind-of@3.2.2
  │ │ │ │   └── kind-of@5.1.0
  │ │ │ ├── extend-shallow@2.0.1
  │ │ │ ├── map-cache@0.2.2
  │ │ │ ├── source-map@0.5.7
  │ │ │ ├─┬ source-map-resolve@0.5.2
  │ │ │ │ ├── atob@2.1.1
  │ │ │ │ ├── decode-uri-component@0.2.0
  │ │ │ │ ├── resolve-url@0.2.1
  │ │ │ │ ├── source-map-url@0.4.0
  │ │ │ │ └── urix@0.1.0
  │ │ │ └── use@3.1.0
  │ │ ├─┬ snapdragon-node@2.1.1
  │ │ │ ├─┬ define-property@1.0.0
  │ │ │ │ └─┬ is-descriptor@1.0.2
  │ │ │ │   ├── is-accessor-descriptor@1.0.0
  │ │ │ │   └── is-data-descriptor@1.0.0
  │ │ │ └─┬ snapdragon-util@3.0.1
  │ │ │   └── kind-of@3.2.2
  │ │ ├── split-string@3.1.0
  │ │ └─┬ to-regex@3.0.2
  │ │   └─┬ safe-regex@1.1.0
  │ │     └── ret@0.1.15
  │ ├─┬ glob-parent@3.1.0
  │ │ ├── is-glob@3.1.0
  │ │ └── path-dirname@1.0.2
  │ ├── inherits@2.0.3
  │ ├─┬ is-binary-path@1.0.1
  │ │ └── binary-extensions@1.11.0
  │ ├─┬ is-glob@4.0.0
  │ │ └── is-extglob@2.1.1
  │ ├─┬ normalize-path@2.1.1
  │ │ └── remove-trailing-separator@1.1.0
  │ ├── path-is-absolute@1.0.1
  │ ├─┬ readdirp@2.1.0
  │ │ ├── graceful-fs@4.1.11
  │ │ ├─┬ minimatch@3.0.4
  │ │ │ └─┬ brace-expansion@1.1.11
  │ │ │   ├── balanced-match@1.0.0
  │ │ │   └── concat-map@0.0.1
  │ │ ├─┬ readable-stream@2.3.6
  │ │ │ ├── core-util-is@1.0.2
  │ │ │ ├── isarray@1.0.0
  │ │ │ ├── process-nextick-args@2.0.0
  │ │ │ ├── safe-buffer@5.1.2
  │ │ │ ├── string_decoder@1.1.1
  │ │ │ └── util-deprecate@1.0.2
  │ │ └── set-immediate-shim@1.0.1
  │ └── upath@1.1.0
  ├── cli-table-redemption@1.0.1
  ├── commander@2.13.0
  ├─┬ cron@1.3.0
  │ └── moment-timezone@0.5.17
  ├─┬ debug@3.1.0
  │ └── ms@2.0.0
  ├── eventemitter2@1.0.5
  ├── fclone@1.0.11
  ├─┬ mkdirp@0.5.1
  │ └── minimist@0.0.8
  ├── moment@2.22.1
  ├─┬ needle@2.2.1
  │ ├── debug@2.6.9
  │ ├─┬ iconv-lite@0.4.23
  │ │ └── safer-buffer@2.1.2
  │ └── sax@1.2.4
  ├─┬ nssocket@0.6.0
  │ ├── eventemitter2@0.4.14
  │ └── lazy@1.0.11
  ├── pidusage@1.2.0
  ├─┬ pm2-axon@3.1.0
  │ ├── amp@0.3.1
  │ ├── amp-message@0.1.2
  │ └── escape-regexp@0.0.1
  ├── pm2-axon-rpc@0.5.1
  ├─┬ pm2-deploy@0.3.9
  │ ├── async@1.5.2
  │ └── tv4@1.3.0
  ├─┬ pm2-multimeter@0.1.2
  │ └── charm@0.1.2
  ├─┬ pmx@1.6.4
  │ ├── deep-metrics@0.0.1
  │ ├── json-stringify-safe@5.0.1
  │ └─┬ vxx@1.2.2
  │   ├─┬ continuation-local-storage@3.2.1
  │   │ ├── async-listener@0.6.9
  │   │ └── emitter-listener@1.1.1
  │   ├── debug@2.6.9
  │   ├── extend@3.0.1
  │   ├── is@3.2.1
  │   ├── lodash.findindex@4.6.0
  │   ├── lodash.isequal@4.5.0
  │   ├── lodash.merge@4.6.1
  │   ├── methods@1.1.2
  │   ├── shimmer@1.2.0
  │   └── uuid@3.2.1
  ├─┬ promptly@2.2.0
  │ └─┬ read@1.0.7
  │   └── mute-stream@0.0.7
  ├── semver@5.5.0
  ├─┬ shelljs@0.7.8
  │ ├─┬ glob@7.1.2
  │ │ ├── fs.realpath@1.0.0
  │ │ ├─┬ inflight@1.0.6
  │ │ │ └── wrappy@1.0.2
  │ │ └── once@1.4.0
  │ ├── interpret@1.1.0
  │ └─┬ rechoir@0.6.2
  │   └─┬ resolve@1.7.1
  │     └── path-parse@1.0.5
  ├─┬ source-map-support@0.5.6
  │ ├── buffer-from@1.0.0
  │ └── source-map@0.6.1
  ├── sprintf-js@1.1.1
  ├── v8-compile-cache@1.1.2
  ├─┬ vizion@0.2.13
  │ └── async@1.5.2
  └─┬ yamljs@0.3.0
    └─┬ argparse@1.0.10
      └── sprintf-js@1.0.3

npm WARN optional SKIPPING OPTIONAL DEPENDENCY: gkt@https://tgz.pm2.io/gkt-1.0.0.tgz (node_modules/pm2/node_modules/gkt):
npm WARN network SKIPPING OPTIONAL DEPENDENCY: connect ETIMEDOUT 163.172.101.189:443
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.1.2 (node_modules/pm2/node_modules/chokidar/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.4: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})

此时基本上构建 node 项目的准备工作就已经完备了,但是此时有一个问题,那就是之前自己安装完上边两条命令之后就以为可以使用了,然后就在 Jenkins 上开始构建,发现总是会报错,说找不到这个命令,改成绝对路径执行就能执行了,后来明白了。

Linux 有不少类似的情况,就像这个 node 一样,解压安装之后创建了软链接,此时只是将源码中带着的命令链接到了/usr/bin 目录下,接下来安装的新命令,并没有被链接过去,因此执行的时候会报找不到这个命令的错误。

那么重新执行一下软链接命令就行了,或者是写入了/etc/profile 中的话,记得在脚本当中及时使用 source 命令对环境进行加载。

ln -s /usr/local/node/bin/* /usr/local/bin/

现在就可以通过准备好了的环境,先在远程服务器上跑一下服务,如果本地可以跑起来,那么接下来的事儿就好办了。

用启动命令跑一下:

第一次启动会有如下输出:

[root@localhost h5-node]# npm run testEnv &
[1] 3854

> 51fanbei-web@0.0.0 testEnv /usr/local/h5-node
> pm2 start ecosystem.json --watch --env test


                        -------------

__/\\\\\\\\\\\\\____/\\\\____________/\\\\____/\\\\\\\\\_____
 _\/\\\/////////\\\_\/\\\\\\________/\\\\\\__/\\\///////\\\___
  _\/\\\_______\/\\\_\/\\\//\\\____/\\\//\\\_\///______\//\\\__
   _\/\\\\\\\\\\\\\/__\/\\\\///\\\/\\\/_\/\\\___________/\\\/___
    _\/\\\/////////____\/\\\__\///\\\/___\/\\\________/\\\//_____
     _\/\\\_____________\/\\\____\///_____\/\\\_____/\\\//________
      _\/\\\_____________\/\\\_____________\/\\\___/\\\/___________
       _\/\\\_____________\/\\\_____________\/\\\__/\\\\\\\\\\\\\\\_
        _\///______________\///______________\///__\///////////////__


                          Community Edition

            Production Process Manager for Node.js applications
                     with a built-in Load Balancer.


                Start and Daemonize any application:
                $ pm2 start app.js

                Load Balance 4 instances of api.js:
                $ pm2 start api.js -i 4

                Monitor in production:
                $ pm2 monitor

                Make pm2 auto-boot at server restart:
                $ pm2 startup

                To go further checkout:
                http://pm2.io/


                        -------------

[PM2] Spawning PM2 daemon with pm2_home=/root/.pm2
[PM2] PM2 Successfully daemonized
[PM2][WARN] Applications 51web not running, starting...
[PM2] App [51web] launched (1 instances)
┌──────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────┬───────────┬──────┬──────────┐
│ App name │ id │ mode │ pid  │ status │ restart │ uptime │ cpu │ mem       │ user │ watching │
├──────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────┼───────────┼──────┼──────────┤
│ 51web    │ 0  │ fork │ 3880 │ online │ 0       │ 0s     │ 3%  │ 13.1 MB   │ root │ enabled  │
└──────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────┴───────────┴──────┴──────────┘
 Use `pm2 show <id|name>` to get more details about an app

[1]+  完成                  npm run testEnv

好啦,起来啦,使用 pm2 list 可以看到服务此刻的状态。

3,部署脚本。

那么,现在是时候完善一波脚本了。

首先是 Jenkins 项目配置处的脚本:此处的脚本任务非常简单,那就是调用一下服务器上的真实脚本,咱有事儿服务器上说,大概就是这么个意思。

内容也非常简单:

source /etc/profile  && /bin/bash /usr/local/scripts/deploy.sh $mode $branch	

注意此处两个变量的来源是上头两个参数化构建出所定义的名字,这里的先后顺序可以自定义,但是要注意上下文调用的时候别搞混了就行。

现在来到 Jenkins 服务器本机完善重要的中转脚本,此脚本主要完成三件事儿:其一是将代码从 Git 仓库拉过来然后推送到远程服务器;其二就是依据选项参数中的变量内容来传递不同的操作内容;其三就是记录每次部署的 git 版本号,从而实现后来的回滚。

或许此时你可以根据我上边给出的思路,先尝试着思索一下这个脚本该怎么完成,我不希望你直接看了我的文章照搬照抄之后什么都没懂,这种废了功夫一无所获的情况,不是我想看到的。

因此,很反感翻页的我,要在这里设置一个翻页。


weinxin
扫码订阅,第一时间获得更新
微信扫码二维码,订阅我们网站的动态,另外不定时发送 WordPress 小技巧,你可以随时退订,欢迎订阅哦~

二丫讲梵 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明<十七>Jenkins实战应用–Jenkins构建nodejs项目
1 2 下一页
喜欢 (4)
[如果想支持本站,可支付宝赞助]
分享 (0)
eryajf
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
(7)个小伙伴在吐槽