如何让Paramiko脚本在命令非成功退出时终止运行?
问题与解答
问题描述
我编写了一个基于Python和Paramiko的脚本,代码如下:
# -*- coding:Utf8 -*- import sys import paramiko from scp import SCPClient #Connect function def createSSHClient(server="ec2-35-180-205-148.eu-west-3.compute.amazonaws.com", port=22, user="admin", key="/home/user/Téléchargements/aws_webforce.pem",password=""): "createSSHClient return SSHClient object from paramiko.client class and connect to server on port using user and key" ssh = paramiko.client.SSHClient() ssh.load_host_keys(key) #ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #to avoid raise SSHException Server XY not found in known_hosts ssh.connect(hostname=server,port=port,username=user,key_filename=key) return ssh #Connecting ssh=createSSHClient() # Define progress callback that prints the current percentage completed for the file def progress(filename, size, sent): sys.stdout.write("%s's progress: %.2f%% \r" % (filename, float(sent)/float(size)*100) ) # SCPCLient takes a paramiko transport and progress callback as its arguments. scp = SCPClient(ssh.get_transport(),progress=progress) #use scp with python: Uploading the 'corrige_exercice1_docker_compose' directory with its content in the # /tmp remote directory scp.put('corrige_exercice1_docker_compose', recursive=True, remote_path='/tmp') scp.close() for cmd in ["sudo apt update", "sudo apt install docker.io", "sudo apt install docker-compose", "cd /tmp/corrige_exercice1_docker_compose && sudo docker-compose up -d", "echo 'done'"]: stdin, stdout, stderr = ssh.exec_command(cmd) stdout_list=stdout.readlines() for txt in stdout_list: print(txt) ssh.close()
最初我将cd /tmp作为单独命令执行,导致docker-compose未在服务器上正常运行,但Paramiko脚本并未终止或报错。请问如何设置Paramiko,使其在命令返回非0退出码时终止脚本运行?我查阅了Paramiko官方文档但未找到相关方法,恳请解答。
解决方案
1. 获取命令退出码并终止脚本
Paramiko的exec_command返回的stdout对象关联的channel可以获取命令的退出状态。调用stdout.channel.recv_exit_status()方法,该方法会阻塞直到命令执行完毕,返回命令的退出码(0表示成功,非0表示失败)。
修改循环内的代码,每次执行命令后检查退出码,若不为0则直接终止脚本:
for cmd in ["sudo apt update", "sudo apt install -y docker.io", # 添加-y避免交互等待 "sudo apt install -y docker-compose", "cd /tmp/corrige_exercice1_docker_compose && sudo docker-compose up -d", "echo 'done'"]: stdin, stdout, stderr = ssh.exec_command(cmd) # 先读取所有输出(避免缓冲区阻塞) stdout_output = stdout.read().decode() stderr_output = stderr.read().decode() if stdout_output: print(stdout_output) if stderr_output: print(stderr_output) # 获取退出码并判断 exit_code = stdout.channel.recv_exit_status() if exit_code != 0: print(f"命令执行失败: {cmd},退出码: {exit_code}") ssh.close() sys.exit(1)
注意:必须先读取stdout和stderr的内容,再调用recv_exit_status(),否则可能因为缓冲区未清空导致命令阻塞。另外在apt install命令中添加-y参数,避免出现交互确认导致命令挂起。
2. 解决单独执行cd命令无效的问题
每个exec_command调用都会创建独立的SSH会话,单独执行cd /tmp不会影响后续命令的工作目录。需要将目录切换和后续命令用&&串联(如你当前的写法),确保所有操作在同一个shell会话中执行。如果cd失败,后续命令不会执行,退出码会反映整个命令链的结果。
内容的提问来源于stack exchange,提问作者user19413311
相关产品推荐
相关产品推荐

