在 pexpect 中同时使用 expect() 和 interact()
Using expect() and interact() simultaneously in pexpect
普遍的问题是,我想使用 pexpect 调用需要 sudo 权限的脚本,但我并不总是想输入我的密码(只输入一次)。
我的计划是使用 pexpect 生成具有 sudo 权限的 bash 会话并从那里调用脚本。基本上我总是想让会话保持忙碌,每当一个脚本停止时,我想开始另一个。但是,虽然脚本是 运行,但我希望用户拥有控制权。含义:
脚本应该在类似 expect("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()。
有没有人知道如何解决这个问题?提前致谢。
您可以利用 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] #
普遍的问题是,我想使用 pexpect 调用需要 sudo 权限的脚本,但我并不总是想输入我的密码(只输入一次)。
我的计划是使用 pexpect 生成具有 sudo 权限的 bash 会话并从那里调用脚本。基本上我总是想让会话保持忙碌,每当一个脚本停止时,我想开始另一个。但是,虽然脚本是 运行,但我希望用户拥有控制权。含义:
脚本应该在类似 expect("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()。
有没有人知道如何解决这个问题?提前致谢。
您可以利用 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] #