Jenkins SSH 远程部署测试环境

1、Jenkins 环境配置

1.1 jenkins 插件

1、 直接安装插件

2、下载插件文件进行安装
jenkins插件下载地址

1.2 SSH 连接远程服务器
  1. Passphrase:服务器账户密码(默认)
  2. Path to key:访问服务器的密钥文件路径
  3. Key:密钥文件内容
  4. SSH Servers:服务器参数设置
    4.1 Name:服务器标识
    4.2 Hostname:服务器IP
    4.3 Username:服务器登录账户
    4.4 Remote Directory:远程服务器的定位目录
    4.5 Passphrase / Password:每个账户单独的密码

2、Jenkins 远程部署

2.1 设置 General
2.2 设置源码管理
2.3 设置构建触发器
2.4 设置构建环境

tomcat_action.py

#!/usr/local/python3
# -*- coding: utf-8 -*-
# @Date    : 2018-04-15 09:00:00
# @Author  : Canon
# @Link    : https://www.python.org
# @Version : 3.6.1

"""
python sys.argv[0] sys.argv[1] sys.argv[2]
sys.argv[0]: 脚本路径
sys.argv[1]: 项目名称
sys.argv[2]: 执行 tomcat 操作 (重启, 启动, 停止)

执行脚本示例:
python /home/tomcat/PyScript/tomcat_action.py PaymentGateway start

支付网关: PaymentGateway
对账平台: AutoCheckInterface
管理后台: AdminSystem
账户后台: NewMerchantSystem
OMS后台: OMS

"""

import os
import sys

# 项目名称
program_name = sys.argv[1].lower()
# 执行 tomcat 操作
action_flag = sys.argv[2].lower()
# tomcat 工作目录路径
work_path = "/home/tomcat/"

program_list = [
    {
        "name": "paymentgateway",
        "instance": ["PG1", "PG2"]},
    {
        "name": "autocheckinterface",
        "instance": ["ACI"]},
    {
        "name": "adminsystem",
        "instance": ["AS1", "AS2"]},
    {
        "name": "newmerchantsystem",
        "instance": ["NM1", "NM2"]},
    {
        "name": "oms",
        "instance": ["OMS"]}
]

for item in program_list:
    if item["name"] == program_name:
        if action_flag == "stop":
            # 停止 tomcat
            for val in item["instance"]:
                os.system("service {0} stop".format(val))
        elif action_flag == "restart":
            # 清除 tomcat 缓存
            for val in item["instance"]:
                os.system("rm -rf {0}/work/Catalina/*".format(work_path+val))
            # 重启 tomcat
            for val in item["instance"]:
                os.system("service {0} restart".format(val))
        elif action_flag == "start":
            # 清除 tomcat 缓存
            for val in item["instance"]:
                os.system("rm -rf {0}/work/Catalina/*".format(work_path+val))
            # 启动 tomcat
            for val in item["instance"]:
                os.system("service {0} start".format(val))

2.5 设置构建

pack_mirror.py

#!/usr/local/python3
# -*- coding: utf-8 -*-
# @Date    : 2018-04-15 09:00:00
# @Author  : Canon
# @Link    : https://www.python.org
# @Version : 3.6.1

"""
python sys.argv[0] sys.argv[1]
sys.argv[0]: 脚本路径
sys.argv[1]: 项目名称

执行脚本示例:
python /home/weblogic/AutoBuild/PyScript/pack_mirror.py PaymentGateway

支付网关: PaymentGateway
对账平台: AutoCheckInterface
管理后台: AdminSystem
账户后台: NewMerchantSystem
OMS后台: OMS

"""

import os
import re
import sys


# 项目名称
program_name = sys.argv[1].lower()

# 拉取 svn 镜像包目录
mirror_path = "/home/weblogic/AutoBuild/MirrorDir"

# 镜像包文件
file_name = ""
# 解压后的目录名称
extract_dir = ""

# 所有项目列表
program_list = [
    {
        "proj_name": "PaymentGateway",
        "exclude_list": "",
        "mirror_file": "PaymentGateway.zip"},
    {
        "proj_name": "AutoCheckInterface",
        "mirror_file": "AutoCheckInterface.zip"},
    {
        "proj_name": "AdminSystem",
        "mirror_file": "AdminSystem.zip"},
    {
        "proj_name": "NewMerchantSystem",
        "mirror_file": "NewMerchantSystem.zip"},
    {
        "proj_name": "oms",
        "mirror_file": "OMS.zip"}
]

for item in program_list:
    if item["proj_name"].lower() == program_name:
        extract_dir = item["proj_name"]
        file_name = item["mirror_file"].lower()

# 获取路径下所有的文件
dir_path = {}
for root, dirs, files in os.walk(mirror_path, topdown=False):
    for name in files:
        file_path = os.path.join(root, name)
        # 转化为小写字母进行比较, 判断路径最后是否包含镜像包名称
        if file_path.lower().endswith(file_name):
            # 判断是否有多个镜像包
            if len(re.findall("/\d{{4}}/{0}.zip".format(extract_dir), file_path, flags=re.IGNORECASE)) == 0:
                print("\n"+"Mirror File:"+file_path)
                os.system("unzip -o {0} -d {1}".format("'"+file_path+"'", mirror_path))
            else:
                dir_path[re.findall("\d{4}", file_path)[-1]] = file_path

if dir_path:
    # 列表按数字顺序排序
    list_key = [key for key in dir_path]
    list_key.sort()
    # 镜像包按从早到晚进行解压
    for num in list_key:
        print("\n"+"Mirror File:"+dir_path[num])
        os.system("unzip -o {0} -d {1}".format("'"+dir_path[num]+"'", mirror_path))

# 打包推送的镜像包
os.system("tar -zcvf {0} -C {1} {2}".format("'"+mirror_path+"/"+extract_dir+".tar.gz"+"'", mirror_path, extract_dir))

conf_warn.py

#!/usr/local/python3
# -*- coding: utf-8 -*-
# @Date    : 2018-04-15 09:00:00
# @Author  : Canon
# @Link    : https://www.python.org
# @Version : 3.6.1

"""
python sys.argv[0] sys.argv[1]
sys.argv[0]: 脚本路径
sys.argv[1]: 项目名称

执行脚本示例:
python /home/mirror/BuildDir/PyScript/conf_warn.py PaymentGateway

支付网关: PaymentGateway
对账平台: AutoCheckInterface
管理后台: AdminSystem
账户后台: NewMerchantSystem
OMS后台: OMS

"""

import os
import sys
import difflib
import smtplib
from email.mime.text import MIMEText


# 项目名称
program_name = sys.argv[1].lower()

# 项目集合
proj_dict = {}

# ---------- 发送邮件相关参数------
# 发件服务器
smtp_server = "smtp.exmail.qq.com"
# 端口
port = 465
# 账号
sender = "[email protected]"
# 密码
psw = "BjF792SFx4FyJEgo"
# 接收人
receiver = ["[email protected]", "[email protected]", "[email protected]"
            "[email protected]", "[email protected]", "[email protected]"]

# ---------- 检查是否存在配置以下文件, 若存在, 则发送邮件给全部测试人员 ------
# 管理后台
proj_as = ['web.xml', 'spring-ehcache.xml', 'spring-servlet.xml', 'spring-proxool.xml', 'spring-ds.xml',
           'spring-druid.xml', 'ehcache.xml', 'log4j.xml', 'struts.xml', 'weblogic.xml', 'urlrewrite.xml']
# 对账平台
proj_ac = ['web.xml', 'ehcache.xml', 'log4j.xml', 'build.xml', 'weblogic.xml', 'daoContext.xml',
           'applicationContext.xml']
# 账户后台
proj_nms = ['spring-servlet.xml', 'web.xml', 'ehcache.xml', 'weblogic.xml', 'toolbox.xml', 'pom.xml']
# 支付网关
proj_pg = ['web.xml', 'log4j.xml', 'proxool.xml', 'NETSConfig.xml', 'weblogic.xml', 'urlrewrite.xml']
# oms 系统
proj_oms = ["logback-spring.xml", "application.yml"]
# MPI       
proj_mpi = ['web.xml', 'log4j.xml', 'proxool.xml', 'weblogic.xml']

# 所有项目
proj_list = [
    {
        "proj_name": "PaymentGateway",
        "patch_file": "/home/mirror/BuildDir/RecDir/PaymentGateway.tar.gz",
        "target_path": ["/usr/local/apps/PG1", "/usr/local/apps/PG2"],
        "conf_file": proj_pg,
        "compare_path": "/home/mirror/BuildDir/CompareDir/PaymentGateway"},
    {
        "proj_name": "AutoCheckInterface",
        "patch_file": "/home/mirror/BuildDir/RecDir/AutoCheckInterface.tar.gz",
        "target_path": ["/usr/local/apps/ACI"],
        "conf_file": proj_ac,
        "compare_path": "/home/mirror/BuildDir/CompareDir/AutoCheckInterface"},
    {
        "proj_name": "AdminSystem",
        "patch_file": "/home/mirror/BuildDir/RecDir/AdminSystem.tar.gz",
        "target_path": ["/usr/local/apps/AS1", "/usr/local/apps/AS2"],
        "conf_file": proj_as,
        "compare_path": "/home/mirror/BuildDir/CompareDir/AdminSystem"},
    {
        "proj_name": "NewMerchantSystem",
        "patch_file": "/home/mirror/BuildDir/RecDir/NewMerchantSystem.tar.gz",
        "target_path": ["/usr/local/apps/NM1", "/usr/local/apps/NM2"],
        "conf_file": ["/home/tomcat/NM1", "/home/tomcat/NM2"],
        "compare_path": "/home/mirror/BuildDir/CompareDir/NewMerchantSystem"},
    {
        "proj_name": "oms",
        "patch_file": "/home/mirror/BuildDir/RecDir/OMS.tar.gz",
        "target_path": ["/usr/local/apps/OMS"],
        "conf_file": proj_oms,
        "compare_path": "/home/mirror/BuildDir/CompareDir/OMS"}
]

for item in proj_list:
    # 清除对比目录下的文件
    os.system("rm -rf {0}/*".format(item["compare_path"]))
    # 获取项目信息
    if item["proj_name"].lower() == program_name:
        proj_dict = item

# 解压镜像包文件
os.system("tar -zxvf {0} -C {1}".format("'"+proj_dict["patch_file"]+"'", proj_dict["compare_path"]))

# 获取对比路径下所有的文件
compare_dir = {}
for root, dirs, files in os.walk(proj_dict["compare_path"], topdown=False):
    for name in files:
        if name in proj_dict["conf_file"]:
            print(name)
            file_path = os.path.join(root, name)
            compare_dir[name] = file_path

# 镜像包中存在的配置文件列表
conf_list = [key for key in compare_dir]

compare_dict = {}
if conf_list:
    # 获取项目路径下所有的文件
    init_dir = {}
    for root, dirs, files in os.walk(proj_dict["target_path"][0], topdown=False):
        for name in files:
            if name in conf_list:
                file_path = os.path.join(root, name)
                init_dir[name] = file_path

                # 配置文件差异对比
                hd = difflib.HtmlDiff()
                init_strs = ''
                with open(init_dir[name],'r') as init:
                    init_strs = init.readlines()
                    init.close()

                compare_strs = ''
                with open(compare_dir[name], 'r') as compare:
                    compare_strs = compare.readlines()
                    compare.close()

                content = hd.make_file(init_strs,compare_strs)
                compare_dict[name] = content

email_body = '''
镜像更新包出现以下文件,需要测试人员进行人工检查:
项目名称: {0}
配置文件: {1}
'''.format(proj_dict["proj_name"], ", ".join(conf_list)) for html_key in compare_dict: email_body = email_body + "

{0}

{1}".format(html_key, compare_dict[html_key]) # 清除对比目录下的文件 for item in proj_list: os.system("rm -rf {0}/*".format(item["compare_path"])) # ---------- 编辑邮件内容 ------ # 邮件内容 body = email_body # 定义邮件正文为 html 格式 msg = MIMEText(body, "html", "utf-8") # 发送人 msg['from'] = sender # 接收人 msg['to'] = ";".join(receiver) # 邮件标题 subject = "镜像环境, 配置文件检查" msg['subject'] = subject # ---------- 发送邮件 ------ if conf_list: try: smtp = smtplib.SMTP() # 连接服务器 smtp.connect(smtp_server) # 登录服务器 smtp.login(sender, psw) except: # 连接服务器 smtp = smtplib.SMTP_SSL(smtpserver, port) # 登录服务器 smtp.login(sender, psw) # 发送邮件 smtp.sendmail(sender, receiver, msg.as_string()) # 关闭服务器 smtp.quit()

update_mirror.py

#!/usr/local/python3
# -*- coding: utf-8 -*-
# @Date    : 2018-04-15 09:00:00
# @Author  : Canon
# @Link    : https://www.python.org
# @Version : 3.6.1

"""
python sys.argv[0] sys.argv[1] sys.argv[2] sys.argv[3]
sys.argv[0]: 脚本路径
sys.argv[1]: 项目名称
sys.argv[2]: svn 的上线包的日期文件名
sys.argv[3]: 执行动作选项名称, "更新" 或者 "回退"

执行脚本示例:
python /home/mirror/BuildDir/PyScript/update_mirror.py PaymentGateway 20180101 更新 

支付网关: PaymentGateway
对账平台: AutoCheckInterface
管理后台: AdminSystem
账户后台: NewMerchantSystem
OMS后台: OMS

"""

import os
import sys

# 项目名称
program_name = sys.argv[1].lower()
# 基准备份标识
base_flag = sys.argv[2]
# 执行动作标识
action_flag = sys.argv[3]

"""
所有项目列表:
proj_name: 项目文件夹名称
bak_path: 备份文件路径
patch_file: 更新包文件
target_path: 更新目标路径
"""
program_list = [
    {
        "proj_name": "PaymentGateway",
        "patch_file": "/home/mirror/BuildDir/RecDir/PaymentGateway.tar.gz",
        "target_path": ["/usr/local/apps/PG1", "/usr/local/apps/PG2"],
        "bak_path": "/home/mirror/BakDir/PaymentGateway"},
    {
        "proj_name": "AutoCheckInterface",
        "patch_file": "/home/mirror/BuildDir/RecDir/AutoCheckInterface.tar.gz",
        "target_path": ["/usr/local/apps/ACI"],
        "bak_path": "/home/mirror/BakDir/AutoCheckInterface"},
    {
        "proj_name": "AdminSystem",
        "patch_file": "/home/mirror/BuildDir/RecDir/AdminSystem.tar.gz",
        "target_path": ["/usr/local/apps/AS1", "/usr/local/apps/AS2"],
        "bak_path": "/home/mirror/BakDir/AdminSystem"},
    {
        "proj_name": "NewMerchantSystem",
        "patch_file": "/home/mirror/BuildDir/RecDir/NewMerchantSystem.tar.gz",
        "target_path": ["/usr/local/apps/NM1", "/usr/local/apps/NM2"],
        "bak_path": "/home/mirror/BakDir/NewMerchantSystem"},
    {
        "proj_name": "oms",
        "patch_file": "/home/mirror/BuildDir/RecDir/OMS.tar.gz",
        "target_path": ["/usr/local/apps/OMS"],
        "bak_path": "/home/mirror/BakDir/OMS"}
]

# 备份文件后缀
suffix = ".tar.gz"


def update_patch(val_list):
    for item in val_list:
        proj_name = item["proj_name"]
        if proj_name.lower() == program_name:
            target = item["target_path"]
            patch = item["patch_file"]
            bak_path = item["bak_path"]
            # 基准备份文件名
            bak_one = bak_path + "/" + proj_name + "1" + "_" + base_flag + suffix
            # 判断基准备份文件是否存在
            if os.path.exists(bak_one):
                for count in range(len(target)):
                    bak_file = bak_path + "/" + proj_name + str(count+1) + "_" + base_flag + suffix
                    # 清除 tomcat 存放的项目
                    os.system("rm -rf {0}/*".format(target[count]))
                    # 更新项目
                    os.system("tar -zxvf {0} -C {1}".format("'"+bak_file+"'", target[count]))
                    os.system("tar -zxvf {0} -C {1}".format("'"+patch+"'", target[count]))
            else:
                for count in range(len(target)):
                    bak_file = bak_path + "/" + proj_name + str(count+1) + "_" + base_flag + suffix
                    # 备份项目
                    os.system("tar -zcvf {0} -C {1} {2}".format(bak_file, target[count], proj_name))
                    # 更新项目
                    os.system("tar -zxvf {0} -C {1}".format("'"+patch+"'", target[count]))


def retro_version(val_list):
    for item in val_list:
        proj_name = item["proj_name"]
        if proj_name.lower() == program_name:
            target = item["target_path"]
            bak_path = item["bak_path"]
            # 基准备份文件名
            bak_one = bak_path + "/" + proj_name + "1" + "_" + base_flag + suffix
            # 判断基准备份文件是否存在
            if os.path.exists(bak_one):
                # 执行回退操作
                for count in range(len(target)):
                    bak_file = bak_path + "/" + proj_name + str(count+1) + "_" + base_flag + suffix
                    # 清除 tomcat 存放的项目
                    os.system("rm -rf {0}/*".format(target[count]))
                    # 解压对应版本的项目
                    os.system("tar -zxvf {0} -C {1}".format("'"+bak_file+"'", target[count]))
            else:
                print("基准备份文件 {0} 不存在, 项目 {1} 回退失败, 请检查是否选择正确".format(bak_one, program_name))

# 执行动作
if action_flag == "更新":
    update_patch(program_list)
elif action_flag == "回退":
    retro_version(program_list)

2.6 设置构建后操作

1、Name:对应于(系统管理 -> 系统设置 -> Publish over SSH配置中的 SSH Server -> Name选项)
2、Source files:发送文件的相对路径,相对于(此项目 General -> 使用自定义的工作空间的目录)
3、Remove prefix:移除 Source files 中的前缀目录,只保留传输的文件
4、Remote directory:相对路径,相对于(系统管理 -> 系统设置 -> Publish over SSH配置中的 Remote Directory选项)
5、Exec command:执行的脚本(Source files 文件发送到远程服务器后执行的脚步)

你可能感兴趣的:(Jenkins SSH 远程部署测试环境)