关于Python paramikomo模块 上传文件时报错的问题记录
前言:公司的java项目,目前没有实现cicd都是手动上传jar包更新的,为了提高自己的工作效率,所以使用了python脚本实现自动化一键部署上线更新。
具体实现
1、目录结构如下: 2、配置文件:没做备注的应该也很好看懂 3、脚本源代码:
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):
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 = paramiko.SSHClient()
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()
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)
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)) 没错就是加一个括号十七成为一个元组!!!
结语:虽然问题很小但是还是卡了我很久,可能是因为太菜了吧!!!哈哈哈!!!希望可以帮到大家!!如果有大神知道为啥之前没有传入元组也可以成功欢迎留言科普!!!
|