2016-10-07 5 views
3

Я работаю над программой python, чтобы помочь с инструментом apt-get. Я хочу использовать pexpect для загрузки выбранного пакета. Я считаю, что я застрял на линии child.expect. Кажется, тайм-аут, когда дело доходит до этой линии.Как выполнить команду root с помощью Pexpect?

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 

UPDATE:

пароль отсылается просто отлично. Он также ожидает следующую строку, но затем вводит «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) 

ответ

1

Пробег: child.expect_exact().

Из документов:

Метод ожидать() ожидает приложения ребенка, чтобы вернуть данную строку. Строка, которую вы указываете, является регулярным выражением, поэтому вы можете сопоставлять сложные шаблоны.

Полезно использовать expect() только в том случае, если цель состоит в том, чтобы соответствовать регулярному выражению.

+0

Это сработало. Теперь он ожидает, что эта строка и я могу отправить пароль. Благодарю. – user2631279

+0

Нет проблем. Рад помочь. –

1

Непосредственная проблема заключается в том, что это:

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

использует регулярное выражение. Конструкция [...] имеет особое значение в регулярных выражениях, поэтому на самом деле вы ожидаете наличия одной из букв «d», «o», «s» или «u», за которой следует текст password for user1:. Но sudo отправляет текст [sudo] первым, и регулярное выражение не совпадает с этим, потому что его последний символ ] не один из этих букв.

Существует множество возможных решений. Вы можете просто привести его в соответствие password for user1:. Вы можете использовать expect_exact(), как предложено JLeClerc (это решение, которое я также предпочитаю). Вы можете избежать скобок в своем регулярном выражении, чтобы они не имели своего обычного значения: \[sudo\] (обратите внимание, что при указании этого как строки Python вам нужно удвоить обратную косую черту или использовать строковый литерал).

Другая проблема заключается в том, что если вы уже указали свой пароль за последние несколько минут, вам может не потребоваться его. Тогда звонок expect(), безусловно, ждет время ожидания. Самый простой способ решить эту проблему - сначала выпустить sudo -k. Вы можете даже сделать это в той же командной строке:

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

Теперь я вижу. Когда я использовал строку, которую вы написали для меня, она дважды вводила команду. Что делает опция -k? Благодарю. – user2631279

+0

Он заставляет 'sudo' снова запрашивать ваш пароль, а не кэшировать его. См. 'Man sudo' – kindall