前言:公司的java项目,目前没有实现cicd都是手动上传jar包更新的,为了提高自己的工作效率,所以使用了python脚本实现自动化一键部署上线更新。
具体实现1、目录结构如下:
2、配置文件:没做备注的应该也很好看懂
3、脚本源代码:
# coding:utf-8
import time
import paramiko
import json
print("=" * 50)
D_R = input("请选择你要进行的 *** 作0发布/1回滚(默认为0):") or "0"
# 上传文件函数
def put_file(ip, port, user, passwd, src_path, dis_path):
# 指定 目标主机的IP和端口
transport = paramiko.Transport(ip, port)
# 建立连接
transport.connect(username=user, password=passwd)
sftp = paramiko.SFTPClient.from_transport(transport)
# 上传
kk = sftp.put(src_path, dis_path)
print(kk)
# 关闭连接
transport.close()
# 执行命令
def to_script(ip, port, user, passwd, bash, model=0):
# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname=ip, port=port, username=user, password=passwd)
if model == 0:
stdin, stdout, stderr = ssh.exec_command(bash)
time.sleep(5)
res, err = stdout.read(), stderr.read()
result = res if res else err
print(result.decode().strip())
else:
chan = ssh.invoke_shell()
out = chan.send(bash)
print(out)
time.sleep(2)
# 关闭连接
ssh.close()
# 生成启停脚本
def re_shell(pck_name, conf):
start_bash = 'nohup java -jar -Dfile.encoding="utf-8" -Dlog4j2.formatMsgNoLookups=true -Xms512m -Xmx512m ' + pck_name + '.jar >nohup.out &'
stop_bash = "SPRINGBOOT_JAR_NAME='" + pck_name + ".ja[r]'\n"
start_file = open('start.sh', 'r+', encoding='UTF-8')
stop_modu_file = open('stop-modu.sh', 'r', encoding='UTF-8')
stop_file = open('stop.sh', 'wb')
config_file = open('ip_conf.txt', 'r+', encoding='UTF-8')
start_file.write(start_bash.strip())
start_file.close()
config_file.write(conf.replace("'", '"').strip())
config_file.close()
stop_modu_text = stop_modu_file.read()
stop_file.write(stop_bash.encode('utf-8'))
stop_file.write(stop_modu_text.encode('utf-8'))
stop_file.close()
# 处理配置文件
host_list = [] # 主机信息
def read_conf_to_dict(): # 解析配置文件
f = open('ip_conf.txt', 'r', encoding='UTF-8')
for i in f.readlines():
line = i.strip()
kk = json.loads(line)
host_list.append(kk)
f.close()
read_conf_to_dict()
# 执行参数
ip_list = host_list[0].get('ip').split() # ip 列表
host_port = host_list[0].get('port') # 端口
host_user = host_list[0].get('user') # 用户名
host_passwd = host_list[0].get('passwd') # 密码
src = host_list[0].get('file_name') + ".jar" # 源文件
host_dist = host_list[0].get('dist_name') # 目标路径
vaersion = host_list[0].get('vaersion') # 是否第一次上传
# 需要执行的命令
mkdir_shell = "mkdir " + host_dist + "package/ -p"
stop_shell = 'cd ' + host_dist + '&& sh stop.sh'
start_shell = 'cd ' + host_dist + ' && sh start.sh \n'
bak_shell = "cd " + host_dist + ";mv " + src + " package/" + src + "-`date +%F`" + "-v" + str(vaersion)
print("=" * 50)
if D_R == "0":
if vaersion == 0:
print("您正在创建一个新项目!")
else:
print("这是您第" + str(vaersion) + "次更新!")
host_list[0]['vaersion'] = vaersion + 1
re_shell(host_list[0].get('file_name'), str(host_list[0]))
for ip in ip_list:
print("=" * 50)
print("[" + ip + "]", end="")
# 第一次上传
if vaersion == 0:
# 创建目录
to_script(ip, host_port, host_user, host_passwd, mkdir_shell)
# 上传脚本
put_file(ip, host_port, host_user, host_passwd, "stop.sh", host_dist + "stop.sh")
put_file(ip, host_port, host_user, host_passwd, "start.sh", host_dist + "start.sh")
# 第一次 发布不需要执行打包
if vaersion != 0:
to_script(ip, host_port, host_user, host_passwd, bak_shell)
# 上传jar包
put_file(ip, host_port, host_user, host_passwd, src, host_dist + src)
# 第一次 发布不需要执行停止
if vaersion != 0:
to_script(ip, host_port, host_user, host_passwd, stop_shell)
# 启动
to_script(ip, host_port, host_user, host_passwd, start_shell, 1)
if vaersion == 0:
print("完成!!!")
else:
print("完成!!!")
elif D_R == "1":
print("您正在进行回滚 *** 作,完成后将回到指定版本!")
print("=" * 50)
vs = input("请选择你要回退到那个版本:")
Rellbak_shell = "cd " + host_dist + ";rm -rf " + src + ";cp package/" + src + "-*" + "-v" + vs + " " + src
for ip in ip_list:
print("=" * 50)
print("[" + ip + "]")
# 停止进程
to_script(ip, host_port, host_user, host_passwd, stop_shell)
# 解压指定版本
to_script(ip, host_port, host_user, host_passwd, Rellbak_shell)
# 启动
to_script(ip, host_port, host_user, host_passwd, start_shell, 1)
print("=" * 50)
print("完成!!!")
else:
print("请输入正确的参数!!!!\n参数0为正常更新发布,参数1为回滚,默认为 0 !!")
print("=" * 50)
由于是脚本所以没有考虑太多的交互和异常处理!!!!至于启动和停止脚本需要根据项目不同进行调整!!!如果想照搬还是不建议的,还是要看懂然后自己能根据不完整的做出来就很Nice!!!不说了咱们回到正题。
具体报错信息如下Linux下
PyCharm中
刚开始的时候按照上面的代码进行上线更新都没有问题,但是后来换到了其他服务器上时就开始报上面的错误了,网上找了很多教程都没有解决问题。
我是如何排查的:1、第一反应就是账号密码错误,但是不是
2、ip或者端口错误,但是也不是
3、权限的问题,经过排查还是不是
4、难道服务器做了限制?? 但是我使用xftp是可以连接上传的,所以也可排除了
破不得以我根据把报错信息,去看了源码:
C:\Users\admin\AppData\Local\Programs\Python\Python310\lib\site-packages\paramiko\transport.py
结合我们自己写的代码和源码,可以发现
官方希望我们传入的Ip和port是一个元组,而我们传入的只是两个分开 变量 transport = paramiko.Transport(ip, port) 所以导致了问题的出现!!!!
作用我只只需要这样修改一下源代码就Ok了:
transport = paramiko.Transport((ip, port)) 没错就是加一个括号十七成为一个元组!!!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)