Jenkins 是一款开源 CI&CD 软件,用于自动化各种任务,包括构建、测试和部署软件;支持各种运行方式,可通过系统包、Docker 或者通过一个独立的 Java 程序等,详见 Jenkins 用户手册

安装

Docker 安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
docker search jenkins
docker pull jenkins/jenkins:lts
#映射本地数据卷时,/data/jenkins_home/ 目录的拥有者为 root 用户,容器中 jenkins 用户的 uid 为 1000。
#mkdir -p /data/jenkins_home
#chown -R 1000:1000 /datajenkins_home/
docker volume create jenkins_data
docker run -d \
-p 8080:8080 \
-p 50000:50000 \
--name jenkins \
--restart=always \
-u app \
-v /var/run/docker.sock:/var/run/docker.sock \
-v jenkins_data:/var/jenkins_home \
jenkins/jenkins:lts

YUM 安装

1
2
3
4
5
6
7
8
9
10
yum install java-1.8.0-openjdk
yum install java-11-openjdk
yum install fontconfig

wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat/jenkins.repo
导入 rpm 密钥
rpm --import https://pkg.jenkins.io/redhat/jenkins.io.key
yum clean all
yum makecache
yum -y install jenkins

报错:“Delta RPMs disabled because /usr/bin/applydeltarpm not installed.”

执行 yum install deltarpm 继续安装
PS.如果报错:No Presto metadata available for Jenkins,这是没有重建 YUM 源缓存,重建继续安装;或者浏览器直接访问 https://get.jenkins.io/redhat/ 下载 rpm 文件安装:

1
2
wget https://get.jenkins.io/redhat/jenkins-2.313-1.1.noarch.rpm
rpm -ivh jenkins-2.313-1.1.noarch.rpm


1
2
yum install -y epel-release
yum install -y daemonize

  • 配置文件:/etc/sysconfig/jenkins
  • 程序目录:/usr/lib/jenkins/
  • rpm -ql jenkins 查询安装路径

注意:如果要修改端口,先修改网页再更改配置文件,否则无法访问。

离线安装

提前准备好 OpenJDK11、Jenkins 安装包及自动部署所需插件等

更多 RPM 包请点击查找

安装 JDK11

1
2
3
mkdir -pv /app/service
tar -zxvf openjdk-11.0.2_linux-x64_bin.tar.gz -C /app/service
mv /app/service/jdk-11.0.2 /app/service/jdk11

设置环境变量

1
2
3
4
5
echo "export JAVA_HOME=/app/service/jdk11" >>  ~/.bashrc
echo "export CLASSPATH=\$CLASSPATH:\$JAVA_HOME/lib" >> ~/.bashrc
echo "export PATH=\$PATH:\$JAVA_HOME/bin" >> ~/.bashrc
source ~/.bashrc
java -version

多版本请直接使用完整路径

安装 Jenkins

如果能联网的话,直接服务器下载 WAR 包,不行下载好上传至服务器

1
2
3
4
5
wget https://updates.jenkins.io/download/war/2.346.1/jenkins.war
mkdir -pv /app/service/jenkins && mv jenkins.war /app/service/jenkins/
mkdir -pv /app/data/jenkins && mkdir -pv /app/logs/jenkins
#查看启动参数
cd /app/service/jenkins && /app/service/jdk11/bin/java -jar jenkins.war --help

创建启动脚本

vi jenkins_service.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#!/bin/bash
set -ue

#全局变量
APP_NAME="Jenkins"
APP_FILE="jenkins.war"
APP_PROT="8888"
APP_LOG="/app/logs/jenkins/jenkins.log"
APP_HOME="/app/data/jenkins"
APP_OPTS="--httpPort=${APP_PROT}"
JAVA_BIN="/app/service/jdk11/bin"
JAVA_OPTS="-server -Xms2g -Xmx2g -Xss512k -Xmn1g -DJENKINS_HOME=${APP_HOME}"

if [ "${#}" -lt 1 ]; then
echo -e "\033[0;31mNone Options! \033[0mUsage Options: \033[0;34m[start|stop|restart|status]\033[0m"
exit 1
fi

function start() {
APP_PS=`ps -ef | grep java | grep $APP_FILE | grep -v grep | wc -l`
APP_PID=`ps -ef | grep java | grep $APP_FILE | grep -v grep | awk '{print $2}'`
if [ ${APP_PS} != 0 ]; then
echo -e "${APP_NAME} Service is Running! PID:\033[0;34m${APP_PID}\033[0m"
else
echo -e "\033[0;31mStarting ${APP_NAME} Service...\033[0m"
nohup ${JAVA_BIN}/java ${JAVA_OPTS} -jar ${APP_FILE} ${APP_OPTS} >> "${APP_LOG}" 2>&1 &
APP_PID=`ps -ef | grep java | grep $APP_FILE | grep -v grep | awk '{print $2}'`
if [ "$?" -eq 0 ]; then
echo -e "${APP_NAME} Service Start Successful! PID:\033[0;34m${APP_PID}\033[0m"
else
echo -e "${APP_NAME} Service Start Failed! See Logs for Details: ${APP_LOG}."
fi
fi
}

function stop() {
APP_PID=`ps -ef | grep java | grep $APP_FILE | grep -v grep | awk '{print $2}'`
if [ "${APP_PID}" ]; then
echo -e "\033[0;31mStopping ${APP_NAME} Service...\033[0m"
kill -9 ${APP_PID}
echo -e "${APP_NAME} Service Stop Successful!"
else
echo -e "${APP_NAME} Service is not Running, Use \033[0;34m<start>\033[0m to Run."
fi
}

function restart() {
APP_PS=`ps -ef | grep java | grep $APP_FILE | grep -v grep | wc -l`
if [ ${APP_PS} = 0 ]; then
start
else
stop
sleep 1
start
fi
}

function status() {
APP_PS=`ps -ef | grep java | grep $APP_FILE | grep -v grep | wc -l`
APP_PID=`ps -ef | grep java | grep $APP_FILE | grep -v grep | awk '{print $2}'`
echo -e "\033[0;31mChecking ${APP_NAME} Service...\033[0m"
if [ ${APP_PS} != 0 ];then
echo -e "${APP_NAME} Service is Running! PID:\033[0;34m${APP_PID}\033[0m"
else
echo -e "${APP_NAME} Service is not Running, Use \033[0;34m<start>\033[0m to Run."
fi
}

case $1 in
"start")
start
;;
"stop")
stop
;;
"restart")
restart
;;
"status")
status
;;
*)
echo -e "\033[0;31mInvalid Options! \033[0mUsage Options: \033[0;34m[start|stop|restart|status]\033[0m"
;;
esac

添加可执行权限
1
2
3
4
5
6
7
chmod +x jenkins_service.sh
#启动服务
./jenkins_service.sh start
#停止服务
./jenkins_service.sh stop
#重启服务
./jenkins_service.sh restart

版本升级

直接替换目录下的 WAR 包即可

1
2
3
4
5
6
systemctl stop jenkins
cd /usr/lib/jenkins
cp jenkins.war jenkins.war.2.346.1
wget https://updates.jenkins.io/download/war/2.375.2/jenkins.war
chmod +x jenkins.war
systemctl start jenkins

离线安装的除了文件目录和启动脚本不一样,其他是一样的

设置

初始化

启动成功以后,浏览器输入 ip:8080 进入页面

使用以下命令获取初始密码

1
docker exec -it jenkins cat /var/jenkins_home/secrets/initialAdminPassword

选择插件进行安装,离线安装的跳过此步骤,直接去看 [[#3.备份迁移]]

等待安装,失败了也没关系,后续可以修改插件中心地址重新安装或者直接将插件拷贝到相应的目录下

界面汉化

安装好插件 Locale 和 Localization: Chinese (Simplified) 后,先设置为 zh_US 重新启动,再设置回来;其他插件重启 Jenkins 后,又出现了部分中文简体不翻译的情况;方法如下,可以完美修复。

  • 将语言设定为 zh_US,Jenkins 切换为英文
  • 调用 restart 重启 Jenkins:http://域名/restart)
  • 再次语言设定为 zh_CN,刷新即可

    备份迁移

    网页登录,系统管理->配置,查看并主目录:/app/data/jenkins,打包需要备份的目录和文件即可
  • config.xml:配置
  • jobs 文件夹:工程
  • users 文件夹:用户
  • plugins 文件夹:插件,jpi 或者 hpi 即可

然后重启:systemctl restart jenkins

插件地址

工具

所在服务器需要安装 git 客户端:yum -y install git

Git

服务器生成 SSH 密钥:ssh-keygen -t rsa -b 4096,还可以拷贝到目标服务器做免密码登录
然后服务器的私钥用来创建 SSH 凭据,点击下图红框按钮进行添加:

选中“SSH Username with private key”,然后下拉到“Private Key”部分,点击“Add”进行添加。
cat /root/.ssh/id_rsa


Gitlab 设置部署密钥:cat /root/.ssh/id_rsa.pub

NodeJS

系统管理->全局工具配置->NodeJS->NodeJS 安装,选择需要的版本,全局 NPM 安装设置为:npm install —registry=https://registry.npm.taobao.org

NET

编译.NET应用程序可通过微软提供的 MSBuild 工具,安装 MSBuild 插件的同时 Jenkins 服务器还需安装 MSBuild

  • Windows 系统可以安装 VS 开发工具,构建出问题的时候打开 VS 调试
  • Linux 系统先安装 Core 或者 Mono
    1
    2
    3
    rpmkeys --import "http://pool.sks-keyservers.net/pks/lookup?op=get&search=0x3fa7e0328081bff6a14da29aa6a19b38d3d831ef"
    su -c 'curl https://download.mono-project.com/repo/centos7-stable.repo | tee /etc/yum.repos.d/mono-centos7-stable.repo'
    yum install mono-devel mono-complete
    上述第一步导入密钥失败,跳过也能安装,后续会自动导入

    插件安装完毕后,进入系统管理->全局工具配置(ConfigureTools)找到 MSBuild 配置选项,并点击新增 MSBuild按钮

    运行 whereis xbuild 查看 Jenkins 中 Path to MSBuild 的位置

    Dashboard -> Manage Jenkins -> Configure Global Security

    管理分配角色

    Java

    构建Java 需要先安装 Maven

    邮件通知

    安装 Email Extension Template 插件,设置系统管理员邮件地址,移动到邮件通知

    配置要通知的 Job,构建后操作

    构建

  • Jenkins 构建 VUE 项目
  • Jenkins 构建 Java 项目
  • Jenkins 构建 .NET 项目

    故障

    AWT is not properly configured on this server.

    https://wiki.jenkins.io/display/JENKINS/Jenkins+got+java.awt.headless+problem

    Host key verification failed

    cat /etc/passwd 可以看到 Jenkins 普通用户无法执行某些系统命令并且没有为 Jenkins 生成过密钥对,也没有将公钥拷到目标服务器上
    1
    2
    3
    4
    sed -i 's/jenkins:\/bin\/false/jenkins:\/bin\/bash/g' /etc/passwd
    su jenkins
    ssh-keygen -t rsa -b 4096
    ssh-copy-id -i /var/lib/jenkins/.ssh/id_rsa.pub root@IP

    Webhook 报错 403

    全局设置 -> 关闭防止跨站请求(高版本需要添加以下启动参数):
    1
    2
    vim /etc/sysconfig/jenkins
    -Dhudson.security.csrf.GlobalCrumbIssuerConfiguration.DISABLE_CSRF_PROTECTION=true

    Jenkins 安全设置后报“HTTP Status 404 j_acegi_security_check”,导致无法登录

    vim /var/lib/jenkins/congi.xml
    1
    <useSecurity>false</useSecurity>