How to perform a root command with Pexpect?

喜欢而已 提交于 2019-12-23 18:31:43

问题


I'm working on a python program to assist with the apt-get tool. I want to use pexpect to download the chosen package. I believe I'm getting stuck at the child.expect line. 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.

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)

回答1:


Try child.expect_exact().

From the docs:

The expect() method waits for the child application to return a given string. 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.




回答2:


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:. 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.

There are numerous possible solutions to this. You can just have it match password for user1:. You can use expect_exact() as suggested by JLeClerc (which is the solution I also favor). 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).

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. The easiest way to address this is to issue sudo -k first. You can even do it on the same command line:

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


来源:https://stackoverflow.com/questions/39907546/how-to-perform-a-root-command-with-pexpect

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!