【问题标题】:A command does not finish when executed using Python Paramiko exec_command使用 Python Paramiko exec_command 执行命令时未完成
【发布时间】:2020-09-05 18:36:03
【问题描述】:

我有一个 Python 程序,它位于远程服务器上,它在运行时将文件上传到 AWS 存储桶。如果我 ssh 到服务器并使用命令 sudo python3 /path/to/backup.py 运行它,它会按预期工作。

我正在编写一个 Python 程序来自动化一个更大的过程,其中包括运行 backup.py。我使用 paramiko 库创建了一个函数来执行此操作。这是命令运行的地方

ssh_stdin, ssh_stdout, ssh_stderr = self.ssh.exec_command('sudo python3 /path/to/backup.py', 1800)
logging.debug(f'ssh_stdout: {ssh_stdout.readline()}')
logging.debug(f'ssh_stderr: {ssh_stderr.readline()}')

我的自动化给了我这个输出:

ssh_stdout: Tue, 19 May 2020 14:36:43 INFO     The COS endpoint is 9.11.200.206, writing to vault: SD_BACKUP_4058

之后程序不做任何事情。当我登录服务器并查看backup.py 的日志时,我可以看到它仍在运行,并且似乎正在上传文件。这是它卡在的代码:

s3_client.upload_file(
    Filename=BACKUP,
    Bucket=BUCKET_NAME,
    Key=SPLIT_FILE_NAME,
    Callback=pp(BACKUP),
    Config=config)

我不明白为什么当我的自动化程序启动时它会卡在这里,而不是当我从终端的命令行运行它时。我在日志中看不到任何对我有帮助的东西。它似乎只是在执行过程中卡在了那个点上。会不会和回调没有返回有关?

【问题讨论】:

    标签: python python-3.x ssh callback paramiko


    【解决方案1】:

    您只读取了输出的一行。

    logging.debug(f'ssh_stdout: {ssh_stdout.readline()}')
    

    如果远程程序产生大量输出,一旦其输出缓冲区填满,程序就会在下次尝试写入一些输出时挂起。


    如果你想让程序结束,你必须继续阅读输出。

    最简单的方法是使用readlinesread

    print(stdout.read())
    

    但这对于像您这样的大型输出来说效率很低。

    相反,您可以逐行读取输出:

    for line in stdout:
        print(line.strip())
    

    当命令也产生错误输出时,它变得更加复杂,因为你必须读取两个输出流。 见Paramiko ssh die/hang with big output

    【讨论】: