【问题标题】:Command output is corrupted when executed using Python Paramiko exec_command使用 Python Paramiko exec_command 执行时命令输出损坏
【发布时间】:2021-06-29 17:59:46
【问题描述】:

我是一名软件测试员,试图验证远程 QNX(一种 BSD 变体)机器上的日志在执行特定操作后是否包含正确的条目。我能够列出日志所在目录的内容,并在命令中使用该信息来读取(真的想使用tail -n XX <file>)文件。到目前为止,我在尝试读取文件时总是得到一个“(没有这样的文件或目录)”

我们使用 Froglogic Squish 进行自动化测试,因为 Windows UI(与 QNX 上的服务器部分交互)是使用标准 Windows 元素的 Qt 扩展构建的。 Squish 使用 Python 2.7,所以我使用的是 Python 2.7。

我正在使用 paramiko 与 QNX 服务器进行 SSH 连接。这对于向同样运行在 QNX 服务器上的模拟器部件发送命令非常有效。

所以,这里是代码。一些描述性名称已更改,以避免让我的雇主感到不安。

import sys
import time
import select

sys.path.append(r"C:\Python27\Lib\site-packages")
sys.path.append(r"C:\Python27\Lib\site-packages\pip\_vendor")
import paramiko

# Import SSH configuration variables
ssh_host    = 'vvv.xxx.yyy.zzz'
thelog_dir  = "/logs/the/"
ssh_user    = 'un'
ssh_pw      = 'pw'


def execute_Command(fullCmd):

    outptLines = []
    #
    # Try to connect to the host.
    # Retry a few times if it fails.
    #
    i = 1
    while True:

        try:
            ssh = paramiko.SSHClient()
            ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            ssh.connect(ssh_host, 22, ssh_user, ssh_pw)
            break
        except paramiko.AuthenticationException:
            log ("Authentication failed when connecting to %s" % ssh_host)
            return 1
        except:
            log ("Could not SSH to %s, waiting for it to start" % ssh_host)
        
        i += 1
        time.sleep(2)

        # If we could not connect within time limit
        if i == 30:
            log ("Could not connect to %s. Giving up" % ssh_host)
            return 1

    # Send the command (non-blocking?)
    stdin, stdout, stderr = ssh.exec_command(fullCmd, get_pty=True)

    for line in iter(stdout.readline, ""):
    outptLines.append(line)

    #
    # Disconnect from the host
    #
    ssh.close()

    return outptLines


def get_Latest_Log():
    fullCmd = "ls -1 %s | grep the_2" %thelog_dir

    files = execute_Command(fullCmd)

    theFile = files[-1]
    return theFile


def main():
    numLines = 20

    theLog = get_Latest_Log()
    print("\n\nThe latest log is %s\n\n" %theLog)

    fullCmd = "cd /logs/the; tail -n 20 /logs/the/%s" %theLog
    #fullCmd = "tail -n 20 /logs/the/%s" %theLog
    print fullCmd
    logLines = execute_Command(fullCmd)

    for line in logLines:
        print line


if __name__ == "__main__":
    # execute only if run as a script
    main()

我尝试使用tailcat 读取文件。我还尝试使用 Paramiko 的 SFTP 客户端 getopen 文件。

在所有情况下,尝试读取文件的响应都会失败——尽管列出目录的内容可以正常工作。 (?!)顺便说一句,日志文件应该可以被“世界”读取。权限是-rw-rw-r--。

我得到的输出是:

"C:\Users\xsat086\Documents\paramikoTest>python SSH_THE_MsgChk.py

The latest log is the_20210628_115455_205.log

cd /logs/the; tail -n 20 /logs/the/the_20210628_115455_205.log

(No such file or directory)the/the_20210628_115455_205.log"

文件名正确。如果我将 tail 命令复制并粘贴到与 QNX 服务器的交互式 SSH 会话中,它可以正常工作。

这是否与这种发送命令方法的“非交互”性质有关?我读到一些 SSH 的实现是建立在一个提供非常有限环境的命令之上的。我看不出这会如何影响这个tail 命令。

还是我在这段代码中做了一些愚蠢的事情?

【问题讨论】:

    标签: python ssh paramiko


    【解决方案1】:

    我无法真正完全解释为什么你会得到你得到的结果。

    但一般来说,损坏的输出是启用而不是处理终端仿真的结果。您可以使用get_pty=True 启用终端仿真。去掉它。自动执行命令时,不应使用终端仿真。

    相关问题:
    Is there a simple way to get rid of junk values that come when you SSH using Python's Paramiko library and fetch output from CLI of a remote machine?

    【讨论】: