从pexpect的sendline读取输出

5 投票
3 回答
31449 浏览
提问于 2025-04-17 18:32

我已经让pexpect正常工作了,但在打印输出时遇到了一些问题。在我下面的测试脚本中,它创建了ssh连接,然后发送了sudo su -,接着输入我的密码,再发送一行需要sudo权限的命令(我还多次添加了p.interact(),以确保它处于root状态)。我遇到的问题是,无法返回我运行的命令的输出。最后,我想运行一些top命令,还有一些du -h和其他更复杂的空间命令。但目前当我尝试打印p.before时,我得到了:

Traceback (most recent call last):
File "./ssh.py", line 37, in <module>
print p.before()
TypeError: 'str' object is not callable

这是我正在使用的脚本(已编辑以去掉我的密码等信息)

#!/usr/bin/env python

import pexpect
import struct, fcntl, os, sys, signal

def sigwinch_passthrough (sig, data):
    # Check for buggy platforms (see pexpect.setwinsize()).
    if 'TIOCGWINSZ' in dir(termios):
        TIOCGWINSZ = termios.TIOCGWINSZ
    else:
        TIOCGWINSZ = 1074295912 # assume
    s = struct.pack ("HHHH", 0, 0, 0, 0)
    a = struct.unpack ('HHHH', fcntl.ioctl(sys.stdout.fileno(), TIOCGWINSZ , s))
    global global_pexpect_instance
    global_pexpect_instance.setwinsize(a[0],a[1])

ssh_newkey = 'Are you sure you want to continue connecting'
p=pexpect.spawn('ssh user@localhost')
i=p.expect([ssh_newkey,'password:',pexpect.EOF,pexpect.TIMEOUT],1)
if i==0:
    print "I say yes"
    p.sendline('yes')
    i=p.expect([ssh_newkey,'password:',pexpect.EOF])
if i==1:
    print "I give password",
    p.sendline("mypassword")
elif i==2:
    print "I either got key or connection timeout"
    pass
elif i==3: #timeout
    pass
global global_pexpect_instance
global_pexpect_instance = p
p.sendline("sudo su -")
p.sendline("mypasswd")
p.sendline("mkdir /home/user/test")
print p.before

我参考了这个链接: http://linux.byexamples.com/archives/346/python-how-to-access-ssh-with-pexpect/

任何帮助都非常感谢。

编辑:正如Armin Rigo在下面指出的,我之前把p.before当成了一个函数来调用,像这样p.before()。这是我犯的一个愚蠢错误,这也解释了为什么今天会出现这个错误,而昨天尝试时没有。修改了脚本后,调整了发送的命令,打印p.before时没有返回任何输出。还有其他方法可以从sendline()命令返回输出吗?

3 个回答

0

p.before 是一个字符串,而不是一个函数。如果你想查看它的内容,你需要写 print p.before。希望这能帮到你。

0

要获取发送命令后完整的输出,可以使用 child.read()

比如:

cmd_resp = pexpect.spawnu(cmd)    # for execution of the command
str_to_search = 'Please Enter The Password'
cmd_resp.sendline('yes')       # for sending the input 'yes'
resp = cmd_resp.expect([str_to_search, 'password:', EOF], timeout=30) # fetch the output status
if resp == 1:
   cmd_resp.sendline(password) 
   resp = cmd_resp.expect([str_to_search, 'outputString:', EOF], timeout=30)
   print(cmd_resp.read()) # to fetch the complete output log
1

使用日志文件,这个日志文件会把终端中的所有输出都存储起来。可以参考下面的示例代码:

child = pexpect.spawn("ssh user@localhost")
child.logfile = open("/tmp/mylog", "w")
child.expect(".*assword:")
child.send("guest\r")
child.expect(".*\$ ")
child.sendline("python -V\r")

打开日志文件,就能看到终端中发生的所有事件。

撰写回答