在pexpect中同时使用expect()和interact()

时间:2017-04-12 13:39:49

标签: python pexpect

一般的问题是,我想使用pexpect来调用需要sudo权限的脚本,但我并不总是想输入我的密码(只有一次)。

我的计划是使用pexpect生成一个带有sudo权限的bash会话并从那里调用脚本。基本上我总是希望保持会话忙,每当一个脚本停止时,我想启动另一个脚本。但是在脚本运行时,我希望用户能够控制。含义:

应该在期望之后调用脚本(" root @"),因此每当会话空闲时,它就会启动另一个脚本。当脚本运行时,interact()会让用户控制他想要提供的可能输入。

我的想法是使用不同的线程来解决这个问题。我的代码(用于概念证明)如下所示:

import pexpect
import threading

class BashInteractThread(threading.Thread):
    def __init__(self, process):
        threading.Thread.__init__(self)
        self.pproc = process

    def run(self):
        self.pproc.interact()


s = pexpect.spawn("/bin/bash", ['-i', '-c', "sudo bash"])

it = BashInteractThread(s)
it.start()

s.expect("root@")
s.sendline("cd ~")
while(s.isalive()):
    pass


s.close()

当我调用此脚本时,它不会给我任何输出,但过程似乎已经开始。不过,我不能用CTRL-C或CTRL-D来杀死进程 - 我必须单独杀死进程。我期望的行为是提示输入密码,然后它应该自动将目录更改为主目录。 我不知道为什么它不起作用,但我想输出只会被转发到interact()或expect()。

有没有人知道如何解决这个问题?提前谢谢。

1 个答案:

答案 0 :(得分:2)

您可以利用interact(output_filter=func)。我刚写了一个简单的例子(没有编码风格!)。它的作用是生成一个Bash shell并重复调用Python以供用户进行交互。要退出陷阱,只需输入(或打印)魔术词LET ME OUT

expect()之后

interact()将不再有效,因此需要手动进行模式匹配工作。

代码:

[STEP 101] # cat interact_with_filter.py
import pexpect, re

def output_filter(s):
    global proc, bash_prompt, filter_buf, filter_buf_size, let_me_out

    filter_buf += s
    filter_buf = filter_buf[-filter_buf_size:]

    if "LET ME OUT" in filter_buf:
        let_me_out = True

    if bash_prompt.search(filter_buf):
        if let_me_out:
            proc.sendline('exit')
            proc.expect(pexpect.EOF)
            proc.wait()
        else:
            proc.sendline('python')

    return s

filter_buf = ''
filter_buf_size = 256
let_me_out = False
bash_prompt = re.compile('bash-[.0-9]+[$#] $')

proc = pexpect.spawn('bash --noprofile --norc')
proc.interact(output_filter=output_filter)

print "BYE"
[STEP 102] #

我们试一试:

[STEP 102] # python interact_with_filter.py
bash-4.4# python
Python 2.7.9 (default, Jun 29 2016, 13:08:31)
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> exit()          <---- user input
bash-4.4# python
Python 2.7.9 (default, Jun 29 2016, 13:08:31)
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> exit()          <---- user input
bash-4.4# python
Python 2.7.9 (default, Jun 29 2016, 13:08:31)
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> LET ME OUT      <---- user input
  File "<stdin>", line 1
    LET ME OUT
         ^
SyntaxError: invalid syntax
>>> exit()          <---- user input
bash-4.4# BYE
[STEP 103] #