如何使用 Pexpect 执行 root 命令?
How to perform a root command with Pexpect?
我正在开发一个 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)
尝试child.expect_exact()
。
来自文档:
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.
只有在需要匹配正则表达式时才使用 expect()
是一种很好的做法。
眼前的问题是:
child.expect('[sudo] password for user1: ')
使用正则表达式。 [...]
结构在正则表达式中具有特殊含义,因此您实际等待的是字母 "d"、"o"、"s" 或 [=33 之一=] 后跟文本 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)
我正在开发一个 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)
尝试child.expect_exact()
。
来自文档:
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.
只有在需要匹配正则表达式时才使用 expect()
是一种很好的做法。
眼前的问题是:
child.expect('[sudo] password for user1: ')
使用正则表达式。 [...]
结构在正则表达式中具有特殊含义,因此您实际等待的是字母 "d"、"o"、"s" 或 [=33 之一=] 后跟文本 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)