【问题标题】:How to perform a root command with Pexpect?如何使用 Pexpect 执行 root 命令?
【发布时间】:2017-02-15 21:08:12
【问题描述】:

我正在开发一个 python 程序来协助 apt-get 工具。我想使用 pexpect 下载选择的包。我相信我被困在 child.expect 线上。说到那条线,它似乎超时了。

butt = "vlc"
child = pexpect.spawn('sudo apt-get install ' + butt)
child.logfile = sys.stdout
child.expect('[sudo] password for user1: ')
child.sendline('mypassword')

这是日志文件。

TIMEOUT: Timeout exceeded.
<pexpect.spawn object at 0xb5ec558c>
version: 3.2
command: /usr/bin/sudo
args: ['/usr/bin/sudo', 'apt-get', 'install', 'vlc']
searcher: <pexpect.searcher_re object at 0xb565710c>
buffer (last 100 chars): '[sudo] password for user1: '
before (last 100 chars): '[sudo] password for user1: '
after: <class 'pexpect.TIMEOUT'>
match: None
match_index: None
exitstatus: None
flag_eof: False
pid: 27641
child_fd: 4
closed: False
timeout: 30
delimiter: <class 'pexpect.EOF'>
logfile: <open file '<stdout>', mode 'w' at 0xb74d8078>
logfile_read: None
logfile_send: None
maxread: 2000
ignorecase: False
searchwindowsize: None
delaybeforesend: 0.05
delayafterclose: 0.1
delayafterterminate: 0.1

更新:

密码发送得很好。它也期望下一行,但随后输入“Y”并且什么也不做。

child = pexpect.spawn('sudo apt-get install ' + butt)
child.logfile = sys.stdout
child.expect_exact('[sudo] password for user1: ')
child.sendline('mypass')
child.expect_exact('Do you want to continue? [Y/n] ')
child.sendline('Y')

已解决:

我需要在最后添加这一行。

child.expect(pexpect.EOF, timeout=None)

【问题讨论】:

  • 仅供参考,运行sudo apt install -y package 将自动回答是。

标签: python linux ubuntu pexpect


【解决方案1】:

试试child.expect_exact()

来自文档:

expect() 方法等待子应用程序返回给定的字符串。您指定的字符串是正则表达式,因此您可以匹配复杂的模式。

只有在意图匹配正则表达式时才使用expect() 是一种很好的做法。

【讨论】:

  • 那行得通。现在它需要那条线,我可以发送密码。谢谢。
  • 没问题。很高兴为您提供帮助。
【解决方案2】:

当前的问题是:

child.expect('[sudo] password for user1: ')

使用正则表达式。 [...] 构造在正则表达式中具有特殊含义,因此您实际等待的是字母“d”、“o”、“s”或“u”之一,后跟文本 password for user1:。但是sudo 首先发送文本[sudo],而正则表达式不匹配,因为它的最后一个字符是],而不是其中一个字母。

对此有许多可能的解决方案。你可以让它匹配password for user1:。您可以按照 JLeClerc 的建议使用expect_exact()(这也是我喜欢的解决方案)。您可以对正则表达式中的括号进行转义,这样它们就没有通常的含义:\[sudo\](请注意,将其指定为 Python 字符串时,您需要将反斜杠加倍或使用原始字符串文字)。

另一个问题是,如果您在过去几分钟内已经输入了密码,系统可能不会提示您输入密码。那么expect() 调用肯定会超时等待它。解决此问题的最简单方法是首先发出sudo -k。您甚至可以在同一命令行上执行此操作:

child = pexpect.spawn('sudo -k; sudo apt-get install ' + butt)

【讨论】:

  • 我现在明白了。当我使用您为我编写的行时,它输入了两次命令。 -k 选项有什么作用?谢谢。
  • 它强制sudo 再次提示您输入密码,而不是缓存它。见man sudo
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-08
  • 2014-12-29
  • 2012-01-21
相关资源
最近更新 更多