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

如何捕获Paramiko SFTPClient get()和put()的执行结果?

捕获SFTP传输的成功状态与错误信息

Paramiko的SFTPClient.get()和put()方法不会返回成功状态,但传输失败时会抛出异常,我们可以通过捕获这些异常来判断结果,并提取错误信息。以下是修改后的代码实现:

修改后的完整代码

import paramiko
from ansible.module_utils.basic import *

def get_sftp_client(host, port, user, password):
    try:
        # Open a transport
        transport = paramiko.Transport((host, port))
        # Auth    
        transport.connect(None, user, password)
        # Get a client object
        sftp = paramiko.SFTPClient.from_transport(transport)
        return (transport, sftp, None)
    except Exception as e:
        return (None, None, str(e))

def transfer_file(params):
    has_changed = False
    user = params['user']
    password = params['password']
    host = params['host']
    port = params['port']
    direction = params['direction']
    src = params['src']
    dest = params['dest']

    transport, sftp, conn_error = get_sftp_client(host, port, user, password)
    if conn_error:
        meta = {
            "source": src,
            "destination": dest,
            "direction": direction,
            "stdout": None,
            "stderr": conn_error
        }
        return (has_changed, meta)

    stdout = None
    stderr = None
    try:
        if direction == 'download':
            sftp.get(src, dest)
        else:
            sftp.put(src, dest)
        has_changed = True  # 传输成功则标记状态变更
    except Exception as e:
        stderr = str(e)
    finally:
        # 确保资源被关闭
        if sftp:
            sftp.close()
        if transport:
            transport.close()

    meta = {
        "source": src,
        "destination": dest,
        "direction": direction,
        "stdout": stdout,
        "stderr": stderr
    }

    return (has_changed, meta)

def main():
    fields = {
        "user": {"required": True, "type": "str"},
        "password": {"required": True, "type": "str", "no_log": True},
        "host": {"required": True, "type": "str"},
        "port": {"type": "int", "default": 22},
        "direction": {
            "type": "str",
            "choices": ["upload", "download"],
            "default": "upload",
        },
        "src": {"type": "path", "required": True},
        "dest": {"type": "path", "required": True},
    }

    module = AnsibleModule(argument_spec=fields)

    # Do the work
    has_changed, result = transfer_file(module.params)

    # 如果有错误信息,返回失败状态
    if result.get('stderr'):
        module.fail_json(msg="SFTP transfer failed", meta=result)
    
    module.exit_json(changed=has_changed, meta=result)

if __name__ == '__main__':
    main()

关键修改说明

  • 连接阶段异常捕获:修改get_sftp_client函数,捕获连接/认证时的异常,返回错误信息,避免模块直接崩溃。
  • 传输阶段异常捕获:将get()/put()调用包裹在try-except块中,捕获所有传输相关异常,将错误信息存入stderr字段。
  • 状态变更标记:传输成功时将has_changed设为True,符合Ansible的状态变更逻辑。
  • 错误处理流程:在main函数中检查stderr字段,若存在错误则调用module.fail_json()返回失败结果,符合Ansible模块的错误输出规范。
  • 资源安全关闭:使用finally块确保SFTP客户端和Transport连接无论成功失败都会被关闭,避免资源泄漏。

内容的提问来源于stack exchange,提问作者Chris F

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 23:00:36