You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 00:36:28