读取在 SSH 服务器上执行的命令的输出,使用 Paramiko 作为字符串,而不是字节

Posted

技术标签:

【中文标题】读取在 SSH 服务器上执行的命令的输出,使用 Paramiko 作为字符串,而不是字节【英文标题】:Read output of a command executed on SSH server with Paramiko as string, not as bytes 【发布时间】:2021-07-14 03:18:28 【问题描述】:

几年前我在 Python 2.x 中编写了一个脚本,并试图将其移植到 3.x 中运行

以下是我正在做的基本工作:NetworkDevices 是一个包含设备列表的主机和访问凭据的文件。DebugFile 是一个输出文件go(取决于调试级别),因此我可以看到设备何时发送了我不期望的内容。

NetworkDevices = open(WorkingDir + DeviceFilename,"r")
DebugFile      = open(WorkingDir + DebugFilename,"w",1)

Try
    # Create instance of SSHClient object
    ssh_pre = paramiko.SSHClient()
    # Automatically add untrusted hosts (make sure okay for security policy in your environment)
    ssh_pre.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    # initiate SSH connection
    ssh_pre.connect(InputVars[0], username=InputVars[1], password=InputVars[2], timeout=10)
    # Use invoke_shell to establish an 'interactive session' 
    Conn = ssh_pre.invoke_shell()
except
    # SSH connection failed, lets try a telnet connection.
    Conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try: 
        # Open Telnet Connection to device
        Conn.connect((InputVars[0],23))
    except
        #Print some error message saying you couldn't connect, blah blah
    else 
        output = str(Conn.recv(10000))
else
    output = str(Conn.recv(10000))

# After I establish my connection via object Conn, I can always just pull more data from 
# the same connection object regardless of whether it's ssh or telnet.

if DebugVar > 3:
    DebugFile.write("Here is the initial response after connecting.\n")
    DebugFile.write("<<<1>>>\n"+output+"\n<<<1>>>\n")

然后根据要收集的内容、设备类型等做一堆事情。

我得到的输出是这样的:

Here is the initial response after connecting:
<<<1>>>
b'\r\nUShaBTC-DCTNW-CORE01#'
<<<1>>>

我想得到这个:

Here is the initial response after connecting.
<<<1>>>
UShaBTC-DCTNW-CORE01#
<<<1>>>

我尝试过使用格式化的字符串文字,但这一直在引导我使用字符串切片,这是我试图避免的。这是我正在尝试做的一件非常简单的事情。接收“块”(使用通用术语)数据,在该数据中查找某个字符串、关键字或结构,然后向连接发送一些内容,并获取另一块数据。

是的,我正在寻找的是我收到的任何一种方式。我仍然可以搜索它,但在某些时候我需要将收到的内容写入一个可读的文件中,而我这样做的运气并不好。

嘿,还有一个问题.... 显然 Python 3 不支持无缓冲文件输出。正如我所展示的,我将数据转储到调试文件中(取决于我的脚本运行的调试级别)。在崩溃中,获取我收到的最后一点数据以找出崩溃的原因非常重要,因此我总是将立即收到的数据写入我的调试文件而不缓冲,这样我以后可以弄清楚它在哪里崩溃以及为什么.有没有办法在没有缓冲的情况下在 Python 3 中写入文件?我回退到 1(而不是 0)的缓冲区,所以我的脚本将在 Python 3.x 中运行,但我仍然可能看不到最后一个(我猜是 1 个字节,实际上无法找出单位是针对那个缓冲区大小的)。

感谢任何帮助。

【问题讨论】:

【参考方案1】:

只需在字节串上调用decode

output = Conn.recv(10000).decode('utf-8')

虽然一般来说,你不应该使用SSHClient.invoke_shell。使用SSHClient.exec_command。见What is the difference between exec_command and send with invoke_shell() on Paramiko?

【讨论】:

谢谢马丁。我终于发现我试图在将类型转换为 str 后对其进行解码,这当然不起作用。一旦我让解码器对 str 进行强制转换,它现在就可以工作了。

以上是关于读取在 SSH 服务器上执行的命令的输出,使用 Paramiko 作为字符串,而不是字节的主要内容,如果未能解决你的问题,请参考以下文章

ssh-keygen 命令

linux之ssh-keygen命令

linux之ssh-keygen命令

Crontab执行脚本中的ssh命令访问被拒绝

在 C++ 中使用管道和超时执行命令(并读取标准输出)

关于在使用ssh命令远程执行命令中有转义字符的问题