简体   繁体   English

如何使用Pexpect执行root命令?

[英]How to perform a root command with Pexpect?

I'm working on a python program to assist with the apt-get tool. 我正在开发一个python程序来协助apt-get工具。 I want to use pexpect to download the chosen package. 我想使用pexpect下载所选的包。 I believe I'm getting stuck at the child.expect line. 我相信我会被困在child.expect线上。 It seems to timeout when it comes to that line. 当谈到那条线时似乎超时了。

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

This is the log file. 这是日志文件。

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

UPDATE: 更新:

The password gets sent just fine. 密码发送得很好。 It also expects the next line as well, but then enters "Y" and does nothing. 它也期望下一行,但然后输入“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')

SOLVED: 解决了:

I needed to add this line at the end. 我需要在最后添加这一行。

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

Try child.expect_exact() . 试试child.expect_exact()

From the docs: 来自文档:

The expect() method waits for the child application to return a given string. expect()方法等待子应用程序返回给定的字符串。 The string you specify is a regular expression, so you can match complicated patterns. 您指定的字符串是正则表达式,因此您可以匹配复杂的模式。

It is good practice to use expect() only when the intent is to match a regular expression. 仅当intent与匹配正则表达式时才使用expect()是一种好习惯。

The immediate problem is that this: 当前的问题是:

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

uses a regular expression. 使用正则表达式。 The [...] construct has special meaning in regular expressions, so what you're actually waiting for there is one of the letters "d", "o", "s", or "u" followed by the text password for user1: . [...]构造在正则表达式中具有特殊含义,因此您实际上正在等待的是其中一个字母“d”,“o”,“s”或“u”后跟文本password for user1: . But sudo is sending the text [sudo] first and the regular expression doesn't match that, because the final character of it is ] not one of those letters. sudo被发送文本[sudo]第一和正则表达式不匹配,因为它的最后一个字符是]不是那些字母中的一个。

There are numerous possible solutions to this. 有许多可能的解决方案。 You can just have it match password for user1: . 你可以让它匹配password for user1: You can use expect_exact() as suggested by JLeClerc (which is the solution I also favor). 您可以使用expect_exact()建议的expect_exact() (我也赞成这个解决方案)。 You can escape the brackets in your regular expression so they don't have their usual meaning: \\[sudo\\] (note that when specifying this as a Python string, you will need to double the backslashes or use a raw string literal). 您可以转义正则表达式中的括号,因此它们没有通常的含义: \\[sudo\\] (请注意,当将其指定为Python字符串时,您需要将反斜杠加倍或使用原始字符串文字)。

The other problem is that if you have already given your password in the last few minutes, you may not be prompted for it. 另一个问题是,如果您在最近几分钟内已经提供了密码,则可能不会提示您输入密码。 Then the expect() call will definitely time out waiting for it. 然后expect()调用肯定会超时等待它。 The easiest way to address this is to issue sudo -k first. 解决这个问题的最简单方法是首先发出sudo -k You can even do it on the same command line: 您甚至可以在同一命令行上执行此操作:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM