jenkins安装与常规配置

前言

非技术分享,仅作为工作交接的备忘录

一、安装Jenkins

  1. 打开官网https://jenkins.io/ 下载得到jenkins.war;
  2. 新建目录:mkdir -p /data/deploy/jenkins;
  3. 将jenkins.war上传到此目录;
  4. 将如下脚本保存成sh脚本,放到jenkins目录;
  5. 给启动脚本与停止脚本可执行权限:
chmod +x /data/deploy/jenkins/*.sh 

启动脚本:startJenkins.sh

# 采用jdk1.8版本,当jdk小于1.7时,XX:MetaspaceSize/XX:MaxMetaspaceSize参数需要替换或直接删除  
# jenkins运行在8001端口
#/bin/sh
nohup java -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -Xmx2048M -jar jenkins.war --httpPort=8001 &

停止脚本:killJenkins.sh

#!/bin/sh
PID=`lsof -i:8001|grep -v PID|awk '{print $2}'`

if [[ "x${PID}" == "x" ]]
then
  echo "没有找到运行的进程,不需要结束"
else
  echo "当前进程PID:${PID},结束当前进程"
  kill -9 ${PID}
fi

二、新建Jenkins Job

添加新的Job时建议从已经有Job中复制
1. 新建自由风格的Job;
2. 填写项目配置:
【General】
项目名称: 根据实际填写
项目描述:留空或根据实际填写
GitLab Connection: 留空
丢弃旧的构建:保持构建的最大个数:通常填5
其余项都可以留空
【源码管理】
选择Git, 填写Repository URL/Branch Specifier
【构建触发器】
勾选:Poll SCM
填写:【/5 * * *】
这里写图片描述
解释说明:每5分钟访问一次git库,如果有更新则自动触发打包,如果没有更新则忽略
【构建环境】
勾选:Color ANSI Console Output
在 ANSI color map中选择:xterm
【构建】
jenkins安装与常规配置_第1张图片

三、jenkins构建步骤解析

当job运行时会依次执行以下步骤:
1. 检查git库上相应的分支是否有更新,如果没有则直接结束,如果有更新则触发Job构建;
2. 从git库上拉取最新的代码;
3. 运行构建命令,比如:gradle clean build dist;
4. 运行自定义脚本:/data/scripts/gralde.py,gradle脚本中完成将dist命令输出的目录打包成zip文件,并推送到应用服务器上,解压替换老版程序;
5. 应用服务器上定时任务(/data/deploy/daemon.sh)监控程序是否更新,发现更新时自动重启应用;

四、gradle脚本详解

#!/usr/bin/env python
# coding:utf-8
from shutil import rmtree
from subprocess import Popen, PIPE, STDOUT
from os.path import exists, join
from os import environ
from fabric.api import run, put, settings, cd, prefix
from fabric.colors import *
from deng.tools import Tools

ROOT_DIR = environ["WORKSPACE"]
JOB_NAME = environ["JOB_NAME"].replace(
            "sit-", "").replace("uat-", "").replace("prod-", "")
# 应用服务器
APP_SERVER = "fhgk-db"
# 应用部署路径
APP_PATH = "/data/deploy"


def analy_subproject(filename="settings.gradle"):
    """用途:分析项目,获得子项目名称
    :param filename: 项目列表定义文件
    :return: 子项目列表
    """
    subprojects = []
    if os.path.isfile(os.path.join(ROOT_DIR, filename)):
        fileobj = open(filename)
    else:
        print red("{}项目找不到文件:{}".format(JOB_NAME,
                  os.path.join(ROOT_DIR, filename)))
        exit(1)
        return []

    for lines in fileobj.readlines():
        if lines.strip().lower().startswith("include"):
            project_name = lines.strip().strip("include").strip().strip("\"")
            subprojects.append(project_name)
    print blue("{}项目包含以下子项目:".format(JOB_NAME))
    Tools.format_print(subprojects)
    return subprojects


def analy_mainproject(subprojects=None):
    """用途:从众多子项目中分析出子主项目
    :param subprojects: 子项目列表
    :return: 主子项目
    """
    if subprojects is None:
        subprojects = analy_subproject()
    for project in subprojects:
        if os.path.isdir(os.path.join(ROOT_DIR,
                                      project,
                                      "build/distributions")):
            print blue("项目【{}】中【{}】为主子项目".format(JOB_NAME, project))
            return project
    print red("项目【{}】找不到主子项目,请检查!".format(JOB_NAME))
    exit(1)


def deploy():
    """用途:部署应用
    """
    package = None
    app_dir = None
    mainproject = analy_mainproject()
    global APP_PATH
    APP_PATH = APP_PATH+'/'+mainproject
    for file in os.listdir(os.path.join(ROOT_DIR,
                                   mainproject,
                                   "build/distributions")):
        if file.startswith(mainproject) and file.endswith('.zip'):
            package = os.path.join(ROOT_DIR,
                                   mainproject,
                                   "build/distributions",
                                   file)
            print blue("本次打包生成安装包路径:\n{}".format(package))
            break
    if package is None:
        print red("找不到安装包:【{}】,请检查!".format(mainproject + '*.zip'))
        exit(1)
    else:
        app_pack = os.path.basename(package)
        app_dir = os.path.basename(package).split('.zip')[0]
    with settings(forward_agend=True,
                  use_ssh_config=True,
                  host_string=APP_SERVER,
                  colorize_errors=True):
        run("mkdir -p {}".format(APP_PATH))
        with cd(APP_PATH):
            print blue("删除原有旧版程序:")
            run("rm -rf *")
            print blue("推送新安装包到应用服务器:\n{}".format(APP_PATH))
            put(package, APP_PATH)
            print blue("开始解压新包:")
            run("unzip -q {}".format(app_pack))
            print blue("设置脚本权限:")
            run("chmod -R 755 ./bin/*")
            run("rm -rf {}".format(app_pack))
            # print blue("kill 原進程:")
            # run("../kill.sh {}".format(mainproject), shell=False)


if __name__ == "__main__":
    deploy()

五、定时任务daemon.sh详解

说明:采用jenkins来重启应用时总是碰到问题,job任务构建完成后,应用进程也自动被kill掉了,找了网上很多资料,但一直没有解决,所以自己写了个简要定时任务来监控应用。
定时任务运行方式:nohup ./daemon.sh &

#!/bin/bash
while true
do
  echo `date`
  # 需要监控的应用目录,添加新程序时将应用目录添加到apps数据中
  APPS=("agw-app" "bns-app" "fohowe-urm-app" "fohowe-web-ec" "register_center")
  # 遍历每个应用
  for APP in ${APPS[@]}
  do
    cd /data/deploy/${APP}
    # 获取应用的进程ID
    PID=`ps -ef|grep /data/deploy/${APP}|grep -v grep|awk '{print $2}'`
    if [[ "x${PID}" == "x" ]]
    then
      echo "${APP}程序没有运行,重新启动......"
      bin/start.sh &
    else
      # pid文件不存在时,说明应用有更新,重启
      if [[ -f "${APP}.pid" ]]
      then
        echo "${APP}进程正常:${PID}"
      else
        echo "${APP}程序找不到PID文件,重新启动......"
        # kill -9 ${PID}
        ps -ef|grep /data/deploy/${APP}|grep -v grep|awk '{print $2}'|xargs kill -9
        bin/start.sh &
      fi
    fi
  done

  # 每次循环60秒
  sleep 30
  echo ""
done

你可能感兴趣的:(CI-持续集成)