在 pexpect 中同时使用 expect() 和 interact() [英] Using expect() and interact() simultaneously in pexpect

查看:188
本文介绍了在 pexpect 中同时使用 expect() 和 interact()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一般问题是,我想使用 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆