【问题标题】:Unexpected output in ParamikoParamiko 中的意外输出
【发布时间】:2019-04-25 02:25:32
【问题描述】:

我正在使用 Paramiko 向路由器发送一些命令,但输出文本几乎无法读取。

如何删除输出中的'b'\r\n

断线的正确方法是什么?

这段代码应该是正确换行的地方:

def print_lines(self, data):
        last_line = data
        if '\n' in data:
            lines = data.splitlines()
            for i in range(0, len(lines)-1):
                print((lines[i]))
            last_line = lines[len(lines) - 1]
            if data.endswith('\n'):
                print(last_line)
                last_line = ''
        return last_line

这是完整的代码:

class ssh:
    shell = None
    client = None
    transport = None

    def __init__(self, address, username, password):
#        print(("Connecting to server on ip", str(address) + "."))
        self.client = paramiko.client.SSHClient()
        self.client.set_missing_host_key_policy(paramiko.client.AutoAddPolicy())
        self.client.connect(address, username=username, password=password, look_for_keys=False)
        self.transport = paramiko.Transport((address, 22))
        self.transport.connect(username=username, password=password)

        thread = threading.Thread(target=self.process)
        thread.daemon = True
        thread.start()

    def close_connection(self):
        if(self.client != None):
            self.client.close()
            self.transport.close()

    def open_shell(self):
        self.shell = self.client.invoke_shell()

    def send_shell(self, command):
        if(self.shell):
            self.shell.send(command + "\n")
        else:
            print("<h1>Shell não aberta.</h1>")

    def process(self):
        global strdata, fulldata
        while True:
            # Print data when available
            if self.shell is not None and self.shell.recv_ready():
                alldata = self.shell.recv(1024)
                while self.shell.recv_ready():
                    alldata += self.shell.recv(1024)
                strdata = strdata + str(alldata)
                fulldata = fulldata + str(alldata)
                strdata = self.print_lines(strdata) # print all received data except last line

    def print_lines(self, data):
        last_line = data
        if '\n' in data:
            lines = data.splitlines()
            for i in range(0, len(lines)-1):
                print((lines[i]))
            last_line = lines[len(lines) - 1]
            if data.endswith('\n'):
                print(last_line)
                last_line = ''
        return last_line


sshUsername = "admin"
sshPassword = "password"
sshServer = "192.168.40.165"

connection = ssh(sshServer, sshUsername, sshPassword)
connection.open_shell()
connection.send_shell('en')
connection.send_shell('conf t')
connection.send_shell('hostname R5')
time.sleep(1)
print('<h1>'+fulldata+'</h1>')   # This contains the complete data received.
connection.close_connection()

我预料到了:

R5#en
R%#conf t
Enter configuration commands, one per line. End with CNTL/Z.
R5(config)#hostname R5
R5(config)#

但这就是结果:

b'\r\nR5#'b'e'b'n'b'\r\n'b'R5#'b'c'b'o'b'n'b'f'b' t'b'\r\n'b'Enter configuration commands, one per line. End with CNTL/Z.\r\nR5(config)#'b'h'b'o'b's'b't'b'n'b'a'b'm'b'e'b' 'b'R'b'5'b'\r\n'b'R5(config)#'

如何正确换行? 请原谅我的大帖子。

【问题讨论】:

  • b'\r\nR5#'b'e'b'n'b'\r\n'b'R5#'b'c'b'o'b'n'b'f'b' t'b'\r\n'b'Enter configuration commands, one per line. End with CNTL/Z.\r\nR5(config)#'b'h'b'o'b's'b't'b'n'b'a'b'm'b'e'b' 'b'R'b'5'b'\r\n'b'R5(config)#' 貌似是多字节对象,是一字节对象还是多字节对象?
  • 它是几个对象,但它表现得像一个对象。如果我使用 .exec_command,我可以拆分行,但我一次只能使用一个命令,但如果我使用 .send_shell,我可以发送多个命令,但不能打印拆分行。
  • 我终于设法在另一个脚本中打破了喜欢,但这带来了其他问题。我在第一篇文章中发布了示例。伙计,我真的需要帮助......
  • 不要更新旧问题,删除更新并提出新问题。
  • 会的。谢谢

标签: python-3.x paramiko


【解决方案1】:

alldata 从 paramiko 接收字节,并且您正在使用 str(bytes),因此您在 b'string' 周围加上引号。您需要使用 decode 来解码字节

alldata_str = alldata.decode()
strdata = strdata + alldata_str
fulldata = fulldata + alldata_str

有一些库可以帮助处理 paramiko,例如基于 paramiko 的路由器 netmiko。我还有一个库可以对一般设备进行终端交互式 ssh https://github.com/filintod/pyremotelogin(也基于 paramiko)。还有用于网络的凝固汽油弹 (https://napalm-automation.net/blog/)。

【讨论】:

  • 感谢您推荐其他平台(库),但我不能为这个特定任务使用其他解决方案。
【解决方案2】:

看起来您正在处理一个 bytes() 对象 (more info),因此您必须使用 decode() 方法将其转换为字符串。

例如,让我们创建一个bytes() 对象并将其转回字符串:

greeting = str("Hello World").encode("UTF-8")
print(greeting)
greeting = greeting.decode("UTF-8")
print(greeting)

或者在你的情况下:

alldata_str = alldata.decode("UTF-8")

警告:Paramiko 的字符串可能有不同的编码,因此请务必仔细检查他们的documentation

祝你好运。

【讨论】:

  • 那真是太好了。我从来没想过。现在我得到一个清晰的文本。我现在要做的就是分割线。我得到这个结果: R5#en R5#conf t 输入配置命令,每行一个。以 CNTL/Z 结尾。 R5(config)#hostname R5 R5(config)#
  • 感谢您的帮助。我一回家就试试。我不知道到底该把它放在哪里,但我会弄清楚的。 :)
  • 好的,我试过 split("\n");拆分(“\r\n”); splitlines()... 仍然无法断线。
  • @Telmo 你是在解码字节之前还是之后这样做?
  • 其实我之前和之后都试过了。我虽然之前应用它更有意义,所以它实际上识别了'\ n'。但是当我使用它(之前或之后)我得到一个空的结果。它不输出任何文本。
猜你喜欢
  • 1970-01-01
  • 2014-10-24
  • 1970-01-01
  • 1970-01-01
  • 2021-10-13
  • 2020-02-21
  • 2012-05-06
  • 2019-03-21
  • 2019-08-29
相关资源
最近更新 更多