Jenkins
是款流行的CI
自动化平台,使用JAVA
语言构建,就其定时任务(Build Trigger
)而言是传统Crontab
理念的拓展,因其部署简单应用比较广泛。
Installation
1. JDK/JRE
因Jenkins
使用Java
构建因此需要JDK/JRE
环境部署,Jenkins
往往需要对应的Java
运行库,因此有可能无法匹配系统发行版Repo
默认提供的Java
版本,需要直接到Oracle
网站下载32/64
位对应系统的tar
包自行部署到Server
。
JDK 8u151 Download Page
: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
因服务器系统为64
位Ubuntu
,选择下载jdk-8u151-linux-x64.tar.gz
并移至服务器,执行以下命令部署Java
环境。
cd /usr/local/java
tar -zxvf jdk-8u151-linux-x64.tar.gz
export JAVA_HOME=/usr/local/java/jdk1.8.0_151
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
which java
java -version
2. Jenkins Master
访问页面https://jenkins.io/download/下载Jenkins
主控程序,与添加Repo
安装相比个人更加喜欢直接执行war
包的部署方式,在上述页面复制Generic Java Package(.war)
的下载链接,随后执行下述命令,可以新建Jenkins
的专属服务用户用于启动Jenkins
程序,也可以图方便直接使用root
账户,这样无需考虑文件系统读写权限配置。
wget http://mirrors.jenkins.io/war/latest/jenkins.war
java -jar jenkins.war
Jenkins
的初次启动会在~/.jenkins/
路径下部署相应的程序文件并生成初始管理员密码回显在程序log
中。
..............
Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:
b186ed1354ee428db55b2101797fcf83
This may also be found at: /root/.jenkins/secrets/initialAdminPassword
...............
使用地址http://<ip>:8080
访问Jenkins GUI
。
使用回显的管理员初始密码继续进入到Jenkins
初始插件安装页面,一般选择Install Suggested Plugins
,随后进入插件安装状态页面。
插件安装完成后在接下来的页面中设置Admin
用户名和密码,至此Jenkins Master
安装完毕。
3. Jenkins Slave/Node
Jenkins
支持分布式网络架构,进入Manage Jenkins - Manage Nodes
页面,可以看到Jenkins
安装完毕后仅有Master
自身一台Server
在列表中用于承担Build Job
。
可以添加其他Server
作为Jenkins
的Slave/Node
承接任务分担Master
负载,点击左侧侧边栏New Node
在页面Node Name
中给Node
命名。
点击OK
后进入Node Configure
,主要需要调整的配置项有# of executors
、Remote root directory
和Launch method
。
其中Launch method
最为重要用来指定在Node
远端启动slave.jar
程序的方法,因Linux
服务器应用的广泛性所以较为通用基于SSH
协议的两种Launch
方法注释如下:
Launch agent via execution of command on the master:
Starts an agent by having Jenkins execute a command from the master. Use this when the master is capable of remotely executing a process on another machine, e.g. via SSH or RSH.
Launch slave agents via SSH:
Starts a slave by sending commands over a secure SSH connection. The slave needs to be reachable from the master, and you will have to supply an account that can log in on the target machine. No root privileges are required.
a.Launch slave agents via SSH
该方法无需提前将slave.jar
部署到Node
服务器,仅需配置Node
服务器IP
和Login Credentials
(常用用户名+密码),Jenkins
会自动调用sftp
传送slave.jar
到Node
并完成该Jar
包的启动。
选择Launch slave agents via SSH
方法并填入正确的Node Host IP
如下图所示。
Credential
需点击add
在弹出的页面框中填入对应的用户名和密码。
随后点击下方save
保存Node
配置自动返回到Node
列表,可以看到新添Node
状态为offline
。
点击Node
名称在弹出的页面中点击Launch Agent
按钮。
Jenkins
启动slave.jar
程序流程如下:
[12/05/17 23:02:25] [SSH] Opening SSH connection to 192.168.19.136:22.
[12/05/17 23:02:25] [SSH] SSH host key matches key in Known Hosts file. Connection will be allowed.
[12/05/17 23:02:25] [SSH] Authentication successful.
[12/05/17 23:02:26] [SSH] The remote user's environment is:
.......
[12/05/17 23:02:26] [SSH] Checking java version of java
[12/05/17 23:02:26] [SSH] java -version returned 1.8.0_151.
[12/05/17 23:02:26] [SSH] Starting sftp client.
[12/05/17 23:02:26] [SSH] Copying latest slave.jar...
[12/05/17 23:02:26] [SSH] Copied 745,674 bytes.
Expanded the channel window size to 4MB
[12/05/17 23:02:26] [SSH] Starting slave process: cd "/root/tmp" && java -jar slave.jar
<===[JENKINS REMOTING CAPACITY]===>channel started
Remoting version: 3.14
This is a Unix agent
Evacuated stdout
Agent successfully connected and online
......
b.Launch agent via execution of command on the master
该方法需要手动部署slave.jar
到Node
并且需要建立Master
到Node SSH
的免密验证用于Jenkins
最终执行ssh <Node_IP> java -jar /xx/slave.jar
以在Node
上启动slave
程序。
选择Launch agent via execution of command on the master
方法,Launch Command
中填入执行命令或者执行脚本,只需保证ssh <Node_IP> java -jar /xx/slave.jar
命令能最终执行即可。
点击下方save
并执行Launch Agent
,Jenkins
处理流程如下:
[12/05/17 23:21:37] Launching agent
$ ssh root@192.168.19.131 java -jar /home/ce/tmp/slave.jar
<===[JENKINS REMOTING CAPACITY]===>channel started
Slave.jar version: 3.10.2
This is a Unix agent
Evacuated stdout
Agent successfully connected and online
c. ssh免密认证
root@ce-virtual-machine:~# ssh-keygen -t rsa
root@ce-virtual-machine:~# ll ~/.ssh/
total 24
drwx------ 2 root root 4096 Dec 5 23:24 ./
drwx------ 9 root root 4096 Dec 5 21:57 ../
-rw-r--r-- 1 root root 408 Dec 5 15:26 authorized_keys
-rw------- 1 root root 1675 Dec 5 23:24 id_rsa
-rw-r--r-- 1 root root 408 Dec 5 23:24 id_rsa.pub
-rw-r--r-- 1 root root 222 Dec 5 12:31 known_hosts
root@ce-virtual-machine:~# scp ~/.ssh/id_rsa.pub [email protected]:~/.ssh/authorized_keys
Jenkins Build Job
Jenkins Master/Slave
部署完成后开始创建Build Job
,点击首页New Item
进入创建Job
页面。
Jenkins
提供的Job
类型按照执行机制大体可以分为Shell-Like
和Pipeline
两类,其中Pipeline
是Jenkins
主推的Job
方式,其语法比较适合流程构建并且Jenkins
对此构建信息回显提供许多原生支持,可参考https://jenkins.io/doc/pipeline/tour/hello-world/;相比之下应用Shell-Like
构建自由风格的Job
方式略显原始,但执行更加灵活,在此选择Freestyle Project
构建进入如下配置界面。
主要配置Build Step
, 点击Add build step
选择Execute Shell
,即可在弹出的Command
栏内编写Shell
脚本,该脚本会在Trigger Build
后依据Jenkins
调度在Master
或Node
上执行。
Jenkins
还原生支持参数传递,如上图所示的环境变量外在General
勾选This project is parameterized
并添加相应的变量即可在Shell
中调用。
在shell
中添加echo $var1; echo $var2
后点击save
,然后在页面点击Build with Parameters
确认后开始构建,Console Output
如下所示。
Started by user ce
Building remotely on test in workspace /root/tmp/workspace/test
[test] $ /bin/sh -xe /tmp/jenkins1445066970670239291.sh
+ echo Start Jenkins Build
Start Jenkins Build
+ pwd
/root/tmp/workspace/test
+ uptime
14:39:12 up 7:09, 1 user, load average: 0.01, 0.06, 0.08
+ echo Test Variable 1
Test Variable 1
+ echo Test Variable 2
Test Variable 2
+ echo Simple Build Completed
Simple Build Completed
Finished: SUCCESS
Jenkins CLI
关于CLI
可参考https://jenkins.io/doc/book/managing/cli/,Jenkins
提供了SSH
交互接口以及封装HTTP API
的Jenkins-cli.jar
。CLI
的配置栏在Manage Jenkins - Jenkins CLI
。
PS: Interactive Scripting
1.实现交互式脚本主要依赖于STDIN
接收命令,例如Shell
中的read
命令,一般使用read -p "Pls input" var
等待并将用户敲入的字符串(以回车键结束)赋值给变量var
,在实际应用中往往后续程序会检测该变量是否空值如果为空则将默认值赋值于变量,这样可以实现用户通过直接回车使用默认值。
#!/bin/bash
read -p "Input para1 [hello]: " para1
[[ $para1 ]] || para1="hello"
echo $para1
read -p "Input para2 [world]: " para2
[[ $para2 ]] || para2="world"
echo $para2
2.因为交互式脚本的存在就引发出如何让交互式脚本自动化的问题,一般可以使用管道实现,例如实现上例脚本自动化的命令如下。
ce@ce-virtual-machine:~/tmp$ echo -e "\n\n" | bash ss.sh
hello
world
ce@ce-virtual-machine:~/tmp$ echo -e "test\ntest\n" | bash ss.sh
test
test
ce@ce-virtual-machine:~/tmp$ cat input.data
test1
test2
ce@ce-virtual-machine:~/tmp$ bash ss.sh < input.data
test1
test2
3.但是对于ssh
、su/sudo
等因安全性禁止从STDIN
读入数据的命令就无法使用管道实现自动输入,为此使用expect
工具。
#!/bin/bash
auto_login_ssh () {
expect -c "set timeout -1;
spawn -noecho ssh -o StrictHostKeyChecking=no $2;
expect *assword:*;
send -- $1\r;
expect *\$*;
send ifconfig\n;
send $3\n;
send exit\n;
expect eof;
"
}
auto_login_ssh 123 bruce@192.168.19.136 'ls\ -al'
4.对于SSH
远程命令免密执行大多通过配置远端信任实现,即将本机公匙填入远端authorized_keys
内可实现本机到远端的免密登录。