【问题标题】:Python pexpect returning the command and the output from the commandPython pexpect 返回命令和命令的输出
【发布时间】:2025-12-11 09:00:01
【问题描述】:

我想连接到运行 CLISH 的服务器,在给出密码提示时提供密码(有效),然后发出“shell”命令将我撞到 bash shell(有效),然后测试是否存在如果文件丢失,则打印“true”;如果存在(有效),则打印“”(空字符串)。

不起作用的是我正在使用“pexpect.before”读回脚本中的内容。我已经要求 pexpect 期待基本提示,然后给我“之前”,据我了解:“在提示匹配之前,你在屏幕上看到了什么?”我不仅按预期获得了“true”或“”(空字符串),而且还获得了我发出的用于测试文件是否存在的命令。

例如,如果我直接通过 SSH 连接到机器,我会这样做: 密码:

我的脚本返回的是命令和响应(问题和答案):

[ ! -f '/etc/logrotate.d/nginx' ] && echo 'true'

true

我只想要响应,要么是“真”,要么是“”。我得到了响应,但我也得到了发出的命令。

你能看出我做错了吗?请帮忙!我想继续使用 pexpect,因为我对 SSH 会话有更复杂的“期望”。

这是我的代码:

def connection(cmd):
    msg_newkey = 'Are you sure you want to continue connecting'
    p=pexpect.spawn('ssh '+user+'@'+host)
    msg = '''Super long welcome message containing your canned warning message, etc.
          myuser@'''+myhost+''''s password:'''
    i=p.expect([msg_newkey,'password:',pexpect.EOF])
    if i==0:
        print "Accepting key."
        p.sendline('yes')
        i=p.expect([msg_newkey,'password:',pexpect.EOF])
    if i==1:
        print "Supplying password"
        p.sendline(passwd)
    elif i==2:
        if "No route to host" in p.before:
            return p.before
        else:
            pass    # Add no functionality, just saying "move on"
    i=p.expect(['MYCLISHPROMPT>',pexpect.EOF])
    if i==0:
            p.sendline('shell')
    i=p.expect(['.*@.*\$',pexpect.EOF])
    if i==0:
            p.sendline(cmd)
    p.expect(['myuser@myhost:',pexpect.EOF])
    return p.before

 def look_for_file(step, filename, mytest):
    cmd = "[ ! -f '"+filename+"' ] && echo '"+mytest+"'"
    results = connection(cmd)
    print "***"+str(result)+"***"
    assert (results == '' or results == 0), "Step failed!  Error: "+results

【问题讨论】:

    标签: python ssh python-2.7 stdout pexpect


    【解决方案1】:

    有一个函数setecho(它是一对getecho)应该控制是否回显发送行中的字符串。

    setecho(self, state)
        This sets the terminal echo mode on or off. Note that anything the
        child sent before the echo will be lost, so you should be sure that
        your input buffer is empty before you call setecho().
    

    但是,这显然不适用于所有情况,您需要使用一些变通方法。一种是像this answer 那样在bash 中打开回声。另一个是用户 pexpect 的函数 readlinereadlines 读取输出并丢弃与给定命令相呼应的第一行。

    【讨论】:

    • 感谢您的意见!我将探索这些选项,并尽快将我的结果发回这里。我遇到了另一个问题,现在正在发布该问题:)
    • 这对我来说非常有效。我现在只得到我的结果而不是我的命令。谢谢!
    【解决方案2】:

    我在一个脚本中遇到了这个问题,我需要将pexpect日志设置为sys.stdout,如下所示:

        shell = pexpect.spawn("bash")
        shell.logfile = sys.stdout
    

    我在这里尝试了其他答案中建议的解决方案,但没有成功;无论如何,传递给sendline() 的字符串都会打印到日志中。

    不过,我发现暂时禁用pexpect日志似乎可以解决问题:

        shell.logfile = None
        shell.sendline(MY_STRING)
        shell.logfile = sys.stdout
    

    【讨论】: