当前位置:首页 > Python教程 > python技巧

Jenkins持续集成-自动化部署脚本的实现《python》

读者须知:
1、本手记本着记续接前面的两张手记内容整理
2、本手记针对tomcat部署测试环境实现
最近工作比较繁忙,导致这章一直拖延,没有太抽出时间来总结。要实现Jenkins端的持续集成,其实在CI服务配置端很容易,难点呢?就是如何实现自动化的部署。我的脚本设计就是为了解决以下难题:
难点一、如何使得自动化部署脚本更通用
我用的脚本,依赖依赖一个配置文件的模块化,让每一个应用业务模块更加通用。自动化所执行的命令呢?
我也是设计想法本着更加通用平台的原则,至少对于tomcat+java or java+socket这种模式通用。
难点二、如何使得自动化的部署简单有效
本脚本,更加切合实际,例:自动化部署关闭tomcat,我们常常会选择catalina.sh stop去关闭,然而这里我选择了kill的方式,如果检测中没有顺利关闭,我将调用kill -9 去直接关闭。(没办法,选择了通用,你是没遇到过tomcat 一直有线程卡住,关闭不了的情况吧。)
难点三、需要让我们自动化的部署实现高的可靠性
体现在:
1、每一次的部署,配置选项中都会进行备份。(备份只一次)
2、服务自动备份完毕后,需要实现检测(这里我在配置模块中有加入日志终端输出)
当然,这个脚本中还有未完成的地方:
1、服务启动后,自动化的检测机制还是太薄弱。
2、暂时此脚本还无法通用到php,python等环境的更多平台
3、代码备份方式上,应该更加具更多灵活性。
这里,如果你觉得我的脚本可以补充,不如大家一起加入进来(留言、或者邮件我jeson@imoocc.com),我也很想学习学习大家的想法。
一、自动化部署原理图示
1、2、3、4 表示执行的4个部署基础步骤
图片描述
二、实现
    1、Tomcat 进程设置唯一标记
用于识别出一个服务器中唯一的Tomcat进程
java -Dmyapp.name=“project_name”
如果用的tomcat我们可以,直接修改启动控制文件catalina.sh。
JAVA_OPTS="-Dmyapp.name:"project_name" -server -Xms1024M -Xmx4096M -Xss512k -XX:+AggressiveOpts -XX:+UseBiasedLocking -XX:PermSize=128M -XX:MaxPermSize=1024M"
    2、实现自动化登录
一般有两种方式:
方式一、模拟用户密码交互方式,大家可以学习家py中依赖pexcept模块。
方式二、用ssh + Key方式,这个是ssh的一种公钥认证机制。本脚本中用的这种,大家自行学习。
3、CI服务器需要在服务端配置rsync服务端
实现中,主要用于客户端服务拖取代码。
4、配置文件解释
[imoocc.com-server] //服务的模块名称,这里需要注意,需要具有唯一性,且服务的进程标示命名一致
CI_IP=ci.iaskjob.com //CI服务器地址
Login_ISA_Key=/back/key/jeson_iaskjob_rsa //登录ISA的key
Project_IP=192.168.10.99 //工程IP
Project_Login_User=root //对应工程机器登录用户
Project_Login_Port=22 //对应工程机器登录端口
Project_Code_File=/tmp/imoocc //对应工程在CI服务器构建后的执行代码目录
Project_Exclude_File="/var/cache","/var/tmp","jdbc.profile" //不需要向线上同步的文件,如配置文件等等
Project_Backup_Dir=/opt/Jenkins_Backup_Dir //工程备份目录
Project_Deploy_Path=/opt/imoocc //工程部署目录
Project_Start_Command=tomcat/bin/catalina.sh start //工程启动方式
Project_Log_Path=/tmp/imoocc.log //启动后日志的查看方式
分享代码如下:

                #
                 -*- coding: utf-8 -*-
                
#
                !/usr/bin/python
                
#
                ########################################################################
                
#
                 File Name: Jenkins_Project_Deploy.py
                
#
                 Program function: ueed for deployment code in CI server.
                
#
                 Author:Jeson
                
#
                 mail:jeson@imoocc.com
                
#
                 Created Time: 一  6/20 19:24:33 2016
                
#
                ========================================================================
                import
                 ConfigParser

                import
                 sys

                from sys import argv
import paramiko

def Gennerate_cmd(Project_Name,CI_IP,Project_Code_File,Project_Exclude_File,Project_Backup_Dir,Project_Deploy_Path,Project_Start_Command,Project_Log_Path):
    cmd = []
    #生成备份命令if Project_Backup_Dir:
        #生成备份原有文件
        cmd.append("mkdir -p /opt/")
        cmd.append("rsync -avzP %s %s && touch /tmp/CI_%s_backuptrue"%(Project_Deploy_Path,Project_Backup_Dir,Project_Name))
    #生成关闭原有进程命令
    cmd.append(test -e /tmp/CI_%s_backuptrue && ps -auxgrep "name:%s"grep -v grepawk ‘{print $2}‘xargs kill%(Project_Name,Project_Name))
    #生成命令-确认原来服务已经顺利关闭
    cmd.append(ps -auxgrep "name:%s"grep -v grepawk ‘{print $2}‘&& touch /tmp/CI_killSucc  ps -auxgrep "name:%s"grep -v grepawk ‘{print $2}‘xargs kill -9%(Project_Name,Project_Name))
    #生成命令-用于同步新的代码文件if Project_Code_File == "":
        cmd.append(test -e "/tmp/CI_%s_killSucc" && rsync -avzP --delete-after --exclude "{%s}" %s::%s %s%(Project_Name,Project_Exclude_File,CI_IP,Project_Name,Project_Deploy_Path))
    else:
        cmd.append(test -e "/tmp/CI_%s_killSucc" && rsync -avzP --delete-after --exclude "{%s}" %s::%s/%s %s%(Project_Name,Project_Exclude_File,CI_IP,Project_Name,Project_Code_File,Project_Deploy_Path))
    #生成命令-用于启动服务    cmd.append(Project_Start_Command)
    #生成命令-查看服务启动后的日志
    cmd.append(tail -n 200 -f %s%Project_Log_Path)
    #生成命令-清理此次生成的临时文件# cmd.append(‘rm -f /tmp/*%s*‘%Project_Name)return cmd

def Login_Execute_Command(Project_IP,Project_Login_Port,Project_Login_User,Login_ISA_Key,cmds):
    Project_Port = int(Project_Login_Port) if Project_Login_Port else 22
    if Project_IP and Project_Login_User and Login_ISA_Key:
        key = paramiko.RSAKey.from_private_key_file(Login_ISA_Key)
        s = paramiko.SSHClient()
        s.load_system_host_keys()
        s.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        s.connect(hostname=Project_IP,port=Project_Port,username=Project_Login_User,pkey=key)
        for cmd_item in cmds:
            stdin,stdout,stderr=s.exec_command(cmd_item)
            print stdout.read()
        return True
    else:
        return false

def main():
    if len(argv) > 2:
        Config_File = argv[1] if argv[1] else"./Jenkins_Project_Deploy.conf "
        Project_Name = argv[2] if argv[2] else""else:
        print"Error 0:Input argv format error! ./Jenkins_Project_Deploy.py ./test.conf testname"
        sys.exit()
    try:
        cf = ConfigParser.ConfigParser()
        cf.read(Config_File)
        CI_IP = cf.get(Project_Name, "CI_IP")
        Project_Code_File = cf.get(Project_Name, "Project_Code_File")
        Project_Exclude_File = cf.get(Project_Name, "Project_Exclude_File")
        Project_Backup_Dir = cf.get(Project_Name, "Project_Backup_Dir")
        Project_Deploy_Path = cf.get(Project_Name, "Project_Deploy_Path")
        Project_Start_Command = cf.get(Project_Name, "Project_Start_Command")
        Project_Log_Path = cf.get(Project_Name, "Project_Log_Path")

        execute_command = Gennerate_cmd(Project_Name,CI_IP,Project_Code_File,Project_Exclude_File,Project_Backup_Dir,Project_Deploy_Path,Project_Start_Command,Project_Log_Path)
        print"{Step 1: Command collected over!}",execute_command
        Project_IP = cf.get(Project_Name, "Project_IP")
        Project_Login_Port = cf.get(Project_Name, "Project_Login_Port")
        Project_Login_User = cf.get(Project_Name, "Project_Login_User")
        Login_ISA_Key = cf.get(Project_Name, "Login_ISA_Key")
    except Exception as e:
        print"Error 1: %s file open or read error!"%Config_File
        sys.exit()
    print"{Step 2:Prepare to loging...}",Project_IP
    result = Login_Execute_Command(Project_IP,Project_Login_Port,Project_Login_User,Login_ISA_Key,cmds=execute_command)
    if result is False:
        print"Error 3:Execute command failed!"if__name__ == __main__:
    main()

 

手记 Jenkins持续集成-自动化部署脚本的实现

Jenkins持续集成-自动化部署脚本的实现 原创

2016-08-28 23:47:54 12643浏览 1评论
分享到
 

幕客技术

Python工程师 关注公众号"幕客技术"

作者的热门手记

  • Jenkins-持续集成平台(安装篇)

    15969浏览 60推荐 1评论
  • 云时代!我们该如何成为一个优秀的运维工程师

    4432浏览 52推荐 4评论
  • 日志大了,怎么办?用我的日志切割脚本吧!

    10008浏览 51推荐 3评论
  • 用Jenkins构建一个新工程,我们一起试一下!

    11317浏览 36推荐 3评论
  • 从小站到大站的部署架构总结

    2347浏览 27推荐 0评论

读者须知:
1、本手记本着记续接前面的两张手记内容整理
2、本手记针对tomcat部署测试环境实现

最近工作比较繁忙,导致这章一直拖延,没有太抽出时间来总结。要实现Jenkins端的持续集成,其实在CI服务配置端很容易,难点呢?就是如何实现自动化的部署。我的脚本设计就是为了解决以下难题:

难点一、如何使得自动化部署脚本更通用

我用的脚本,依赖依赖一个配置文件的模块化,让每一个应用业务模块更加通用。自动化所执行的命令呢?
我也是设计想法本着更加通用平台的原则,至少对于tomcat+java or java+socket这种模式通用。

难点二、如何使得自动化的部署简单有效

本脚本,更加切合实际,例:自动化部署关闭tomcat,我们常常会选择catalina.sh stop去关闭,然而这里我选择了kill的方式,如果检测中没有顺利关闭,我将调用kill -9 去直接关闭。(没办法,选择了通用,你是没遇到过tomcat 一直有线程卡住,关闭不了的情况吧。)
难点三、需要让我们自动化的部署实现高的可靠性
体现在:
1、每一次的部署,配置选项中都会进行备份。(备份只一次)
2、服务自动备份完毕后,需要实现检测(这里我在配置模块中有加入日志终端输出)

当然,这个脚本中还有未完成的地方:
1、服务启动后,自动化的检测机制还是太薄弱。
2、暂时此脚本还无法通用到php,python等环境的更多平台
3、代码备份方式上,应该更加具更多灵活性。
这里,如果你觉得我的脚本可以补充,不如大家一起加入进来(留言、或者邮件我jeson@imoocc.com),我也很想学习学习大家的想法。


一、自动化部署原理图示
1、2、3、4 表示执行的4个部署基础步骤
技术分享图片
二、实现

  • 1、Tomcat 进程设置唯一标记

用于识别出一个服务器中唯一的Tomcat进程
java -Dmyapp.name=“project_name”
如果用的tomcat我们可以,直接修改启动控制文件catalina.sh。
JAVA_OPTS="-Dmyapp.name:"project_name" -server -Xms1024M -Xmx4096M -Xss512k -XX:+AggressiveOpts -XX:+UseBiasedLocking -XX:PermSize=128M -XX:MaxPermSize=1024M"

  • 2、实现自动化登录

一般有两种方式:
方式一、模拟用户密码交互方式,大家可以学习家py中依赖pexcept模块。
方式二、用ssh + Key方式,这个是ssh的一种公钥认证机制。本脚本中用的这种,大家自行学习。

3、CI服务器需要在服务端配置rsync服务端
实现中,主要用于客户端服务拖取代码。

4、配置文件解释
[imoocc.com-server] //服务的模块名称,这里需要注意,需要具有唯一性,且服务的进程标示命名一致
CI_IP=ci.iaskjob.com //CI服务器地址
Login_ISA_Key=/back/key/jeson_iaskjob_rsa //登录ISA的key
Project_IP=192.168.10.99 //工程IP
Project_Login_User=root //对应工程机器登录用户
Project_Login_Port=22 //对应工程机器登录端口
Project_Code_File=/tmp/imoocc //对应工程在CI服务器构建后的执行代码目录
Project_Exclude_File="/var/cache","/var/tmp","jdbc.profile" //不需要向线上同步的文件,如配置文件等等
Project_Backup_Dir=/opt/Jenkins_Backup_Dir //工程备份目录
Project_Deploy_Path=/opt/imoocc //工程部署目录
Project_Start_Command=tomcat/bin/catalina.sh start //工程启动方式
Project_Log_Path=/tmp/imoocc.log //启动后日志的查看方式


分享代码如下:

                            
                                # -*- coding: utf-8 -*-
                                #!/usr/bin/python
                                #########################################################################
                                # File Name: Jenkins_Project_Deploy.py
                                # Program function: ueed for deployment code in CI server.
                                # Author:Jeson
                                # mail:jeson@imoocc.com
                                # Created Time: 一  6/20 19:24:33 2016
                                #========================================================================
                                import
                                ConfigParser
                                import
                                 sys

                                from
                                 sys 
                                import
                                 argv

                                import
                                 paramiko


                                def
                                Gennerate_cmd
                                (
                                Project_Name
                                ,
                                CI_IP
                                ,
                                Project_Code_File
                                ,
                                Project_Exclude_File
                                ,
                                Project_Backup_Dir
                                ,
                                Project_Deploy_Path
                                ,
                                Project_Start_Command
                                ,
                                Project_Log_Path
                                ):
                                
    cmd 
                                =
                                []
                                #生成备份命令
                                if
                                Project_Backup_Dir
                                :
                                #生成备份原有文件
                                
        cmd
                                .
                                append
                                (
                                "mkdir -p /opt/"
                                )
                                
        cmd
                                .
                                append
                                (
                                "rsync -avzP %s %s && touch /tmp/CI_%s_backuptrue"
                                %(
                                Project_Deploy_Path
                                ,
                                Project_Backup_Dir
                                ,
                                Project_Name
                                ))
                                #生成关闭原有进程命令
                                
    cmd
                                .
                                append
                                (
                                ‘test -e /tmp/CI_%s_backuptrue && ps -auxgrep "name:%s"grep -v grepawk ‘{print $2}‘xargs kill‘
                                %(
                                Project_Name
                                ,
                                Project_Name
                                ))
                                #生成命令-确认原来服务已经顺利关闭
                                
    cmd
                                .
                                append
                                (
                                ‘ps -auxgrep "name:%s"grep -v grepawk ‘{print $2}‘&& touch /tmp/CI_killSucc  ps -auxgrep "name:%s"grep -v grepawk ‘{print $2}‘xargs kill -9‘
                                %(
                                Project_Name
                                ,
                                Project_Name
                                ))
                                #生成命令-用于同步新的代码文件
                                if
                                Project_Code_File
                                ==
                                ""
                                :
                                
        cmd
                                .
                                append
                                (
                                ‘test -e "/tmp/CI_%s_killSucc" && rsync -avzP --delete-after --exclude "{%s}" %s::%s %s‘
                                %(
                                Project_Name
                                ,
                                Project_Exclude_File
                                ,
                                CI_IP
                                ,
                                Project_Name
                                ,
                                Project_Deploy_Path
                                ))
                                else
                                :
                                
        cmd
                                .
                                append
                                (
                                ‘test -e "/tmp/CI_%s_killSucc" && rsync -avzP --delete-after --exclude "{%s}" %s::%s/%s %s‘
                                %(
                                Project_Name
                                ,
                                Project_Exclude_File
                                ,
                                CI_IP
                                ,
                                Project_Name
                                ,
                                Project_Code_File
                                ,
                                Project_Deploy_Path
                                ))
                                #生成命令-用于启动服务
                                
    cmd
                                .
                                append
                                (
                                Project_Start_Command
                                )
                                #生成命令-查看服务启动后的日志
                                
    cmd
                                .
                                append
                                (
                                ‘tail -n 200 -f %s‘
                                %
                                Project_Log_Path
                                )
                                #生成命令-清理此次生成的临时文件
                                # cmd.append(‘rm -f /tmp/*%s*‘%Project_Name)
                                return
                                 cmd


                                def
                                Login_Execute_Command
                                (
                                Project_IP
                                ,
                                Project_Login_Port
                                ,
                                Project_Login_User
                                ,
                                Login_ISA_Key
                                ,
                                cmds
                                ):
                                Project_Port
                                =
                                int
                                (
                                Project_Login_Port
                                )
                                if
                                Project_Login_Port
                                else
                                22
                                if
                                Project_IP
                                and
                                Project_Login_User
                                and
                                Login_ISA_Key
                                :
                                
        key 
                                =
                                 paramiko
                                .
                                RSAKey
                                .
                                from_private_key_file
                                (
                                Login_ISA_Key
                                )
                                
        s 
                                =
                                 paramiko
                                .
                                SSHClient
                                ()
                                
        s
                                .
                                load_system_host_keys
                                ()
                                
        s
                                .
                                set_missing_host_key_policy
                                (
                                paramiko
                                .
                                AutoAddPolicy
                                ())
                                
        s
                                .
                                connect
                                (
                                hostname
                                =
                                Project_IP
                                ,
                                port
                                =
                                Project_Port
                                ,
                                username
                                =
                                Project_Login_User
                                ,
                                pkey
                                =
                                key
                                )
                                for
                                 cmd_item 
                                in
                                 cmds
                                :
                                
            stdin
                                ,
                                stdout
                                ,
                                stderr
                                =
                                s
                                .
                                exec_command
                                (
                                cmd_item
                                )
                                print
                                 stdout
                                .
                                read
                                ()
                                return
                                True
                                else
                                :
                                return
                                false
                                def
                                 main
                                ():
                                if
                                 len
                                (
                                argv
                                )
                                >
                                2
                                :
                                Config_File
                                =
                                 argv
                                [
                                1
                                ]
                                if
                                 argv
                                [
                                1
                                ]
                                else
                                "./Jenkins_Project_Deploy.conf "
                                Project_Name
                                =
                                 argv
                                [
                                2
                                ]
                                if
                                 argv
                                [
                                2
                                ]
                                else
                                ""
                                else
                                :
                                print
                                "Error 0:Input argv format error! ./Jenkins_Project_Deploy.py ./test.conf testname"
                                
        sys
                                .
                                exit
                                ()
                                try
                                :
                                
        cf 
                                =
                                ConfigParser
                                .
                                ConfigParser
                                ()
                                
        cf
                                .
                                read
                                (
                                Config_File
                                )
                                
        CI_IP 
                                =
                                 cf
                                .
                                get
                                (
                                Project_Name
                                ,
                                "CI_IP"
                                )
                                Project_Code_File
                                =
                                 cf
                                .
                                get
                                (
                                Project_Name
                                ,
                                "Project_Code_File"
                                )
                                Project_Exclude_File
                                =
                                 cf
                                .
                                get
                                (
                                Project_Name
                                ,
                                "Project_Exclude_File"
                                )
                                Project_Backup_Dir
                                =
                                 cf
                                .
                                get
                                (
                                Project_Name
                                ,
                                "Project_Backup_Dir"
                                )
                                Project_Deploy_Path
                                =
                                 cf
                                .
                                get
                                (
                                Project_Name
                                ,
                                "Project_Deploy_Path"
                                )
                                Project_Start_Command
                                =
                                 cf
                                .
                                get
                                (
                                Project_Name
                                ,
                                "Project_Start_Command"
                                )
                                Project_Log_Path
                                =
                                 cf
                                .
                                get
                                (
                                Project_Name
                                ,
                                "Project_Log_Path"
                                )
                                

        execute_command 
                                =
                                Gennerate_cmd
                                (
                                Project_Name
                                ,
                                CI_IP
                                ,
                                Project_Code_File
                                ,
                                Project_Exclude_File
                                ,
                                Project_Backup_Dir
                                ,
                                Project_Deploy_Path
                                ,
                                Project_Start_Command
                                ,
                                Project_Log_Path
                                )
                                print
                                "{Step 1: Command collected over!}"
                                ,
                                execute_command
        
                                Project_IP
                                =
                                 cf
                                .
                                get
                                (
                                Project_Name
                                ,
                                "Project_IP"
                                )
                                Project_Login_Port
                                =
                                 cf
                                .
                                get
                                (
                                Project_Name
                                ,
                                "Project_Login_Port"
                                )
                                Project_Login_User
                                =
                                 cf
                                .
                                get
                                (
                                Project_Name
                                ,
                                "Project_Login_User"
                                )
                                Login_ISA_Key
                                =
                                 cf
                                .
                                get
                                (
                                Project_Name
                                ,
                                "Login_ISA_Key"
                                )
                                except
                                Exception
                                as
                                 e
                                :
                                print
                                "Error 1: %s file open or read error!"
                                %
                                Config_File
                                
        sys
                                .
                                exit
                                ()
                                print
                                "{Step 2:Prepare to loging...}"
                                ,
                                Project_IP
                                
    result 
                                =
                                Login_Execute_Command
                                (
                                Project_IP
                                ,
                                Project_Login_Port
                                ,
                                Project_Login_User
                                ,
                                Login_ISA_Key
                                ,
                                cmds
                                =
                                execute_command
                                )
                                if
                                 result 
                                is
                                False
                                :
                                print
                                "Error 3:Execute command failed!"
                                if
                                 __name__ 
                                ==
                                ‘__main__‘
                                :
                                
    main
                                ()
                            
                        
相关标签: JAVA 云计算 测试

本文原创发布于慕课网 ,转载请注明出处,谢谢合作!

 

相关阅读

  • 删除数组中的某个(多个)元素(分别用数组和集合的办法删除)

  • Java中Junit4测试实例

  • Spring+SpringMVC+MyBatis+easyUI整合优化篇(三)代码测试

  • Spring+SpringMVC+MyBatis+easyUI整合优化篇(四)单元测试实例

  • Spring+SpringMVC+MyBatis+easyUI整合优化篇(五)MockMvc服务端的单元测试

添加评论

技术分享图片
 
 
1评论

老师为什么不用python的fabric模块自动部署打包

0 回复 2017-09-14 23:13:40
 
 
 

Copyright ? 2017 imooc.com All Rights Reserved | 京ICP备 13046642号-2

 

原文:http://www.cnblogs.com/abc8023/p/8056897.html


【说明】本文章由站长整理发布,文章内容不代表本站观点,如文中有侵权行为,请与本站客服联系(QQ:254677821)!

相关教程推荐

其他课程推荐