在 pexpect 中同时使用 expect() 和 interact() [英] Using expect() and interact() simultaneously in pexpect
问题描述
一般问题是,我想使用 pexpect 调用需要 sudo 权限的脚本,但我并不总是想输入我的密码(只输入一次).
The general problem is, that I want to use pexpect to call scripts that require sudo rights, but I don't always want to enter my password (only once).
我的计划是使用 pexpect 生成具有 sudo 权限的 bash 会话并从那里调用脚本.基本上我总是想让会话保持忙碌,每当一个脚本停止时,我想启动另一个.但是在脚本运行时,我希望用户拥有控制权.含义:
My plan is to use pexpect to spawn a bash session with sudo rights and to call scripts from there. Basically I always want to keep the session busy, whenever one script stopped, I want to start another. But while the scripts are running, I want the user to have control. Meaning:
脚本应该在诸如expect("root@")之类的之后调用,所以每当会话空闲时,它就会启动另一个脚本.当脚本运行时,interact() 让用户控制他想要提供的可能输入.
The scripts should be called after something like expect("root@"), so whenever the session is idle, it starts another script. While the scripts are running interact() is giving the user control of possible input he wants to give.
我的想法是使用不同的线程来解决这个问题.我的代码(用于概念验证)如下所示:
My idea was to use different threads to to solve this problem. My code (for the proof of concept) looks like this:
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 来终止该进程——我必须单独终止该进程.我期望的行为是提示输入密码,然后它应该自动将目录更改为主目录.我不完全知道为什么它不起作用,但我想输出只会转发到交互()或期望().
When I call this script, it does not give me any output, but the process seems to have been started. Still, I cannot CTRL-C or CTRL-D to kill the process - I have to kill the process separately. The behavior I would expect, would be to get prompted to enter a password and after that it should automatically change the directory to the home directory. I don't exactly know why it does not work, but I guess the output only gets forwarded either to interact() or to expect().
有没有人知道如何解决这个问题?提前致谢.
Does anyone have an idea on how to solve this? Thanks in advance.
推荐答案
您可以利用 interact(output_filter=func)
.我只是写了一个简单的例子(没有编码风格!).它的作用是生成一个 Bash
shell 并重复调用 Python
以便用户与之交互.要退出陷阱,只需输入(或打印)魔语LET ME OUT
.
You can take advantage of interact(output_filter=func)
. I just wrote a simple example (no coding style!). What it does is spawn a Bash
shell and repeatedly invoke Python
for the user to interact with. To exit the trap, just input (or print) the magic words LET ME OUT
.
expect()
在interact()
之后就不能再工作了,所以需要手动做模式匹配工作.
expect()
would not work anymore after interact()
, so need to do the pattern matching work manually.
代码:
[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] #
这篇关于在 pexpect 中同时使用 expect() 和 interact()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!