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个部署基础步骤

57c3008c00018bbe14080812.png

二、实现

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#========================================================================

importConfigParserimportsysfrom sys importargvimportparamikodefGennerate_cmd(Project_Name,CI_IP,Project_Code_File,Project_Exclude_File,Project_Backup_Dir,Project_Deploy_Path,Project_Start_Command,Project_Log_Path):

cmd=[]#生成备份命令

ifProject_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)

returncmddefLogin_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 andLogin_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 incmds:

stdin,stdout,stderr=s.exec_command(cmd_item)printstdout.read()returnTrueelse:returnfalsedefmain():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")exceptException 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 isFalse:print "Error 3:Execute command failed!"

if __name__ == '__main__':

main()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值