使用 pexpect 时,您应该始终在 send 之后执行 expect,以便向前移动 pexpect 光标。否则,pexpect(不是贪婪的)将在前 2000 个字符内的搜索字符串的第一个实例处停止,并且它可能会在当前命令后面出现几个命令。
例如在spawn之后:
child.sendline("df -h") # Prints the directory listing and a prompt
child.sendline("lscpu") # Prints the architecture information and a prompt
child.sendline("sudo ls /") # Expects a password, then prints a directory listing
child.expect(['password','[sudo]','[#\$]']) # Finds the password prompt, since it is listed first
child.sendline("correctpassword")
child.expect(['password','[sudo]','[#\$]']) # Finds the earlier sudo prompt, since it was not consumed in the previous expect, and it is listed before the prompt!
我简化并测试了您的代码:
注意 - 使用 Python 3.9 在 Linux 5.14.16 上测试。远程机器是 Ubuntu 8.04。
import sys
import pexpect
try:
child = pexpect.spawn(
'ssh -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null ' +
'-oPubkeyAuthentication=no -oConnectTimeout=5 someuser@192.168.x.x')
child.logfile = sys.stdout.buffer
index = child.expect_exact(['password:',
'Network is unreachable',
'Connection timed out',
'No address associated with hostname',
'Could not resolve hostname', ])
if index == 0:
child.sendline('correctpassword')
# Use expect_exact to avoid misinterpreting characters as regex delimiters
child.expect_exact('$')
else:
raise RuntimeError('Unable to SSH: Found index {0}'.format(index))
child.sendline('df -h')
child.expect_exact('$')
child.sendline('lshw') # my remote machine does not use lscpu
child.expect_exact('$')
child.sendline('sudo ls /')
index = child.expect_exact(['password', '$', ])
if index == 0:
child.sendline('correctpassword')
# Use expect_exact to avoid misinterpreting characters as regex delimiters
child.expect_exact('$')
# ... add additional code here ...
child.sendline('exit')
child.expect_exact(['closed', '$', ])
child.close()
except pexpect.TIMEOUT:
print('Error: Unable to find the expect search string.\n' +
pexpect.ExceptionPexpect(pexpect.TIMEOUT).get_trace())
except pexpect.EOF:
print('Error: Child closed unexpectedly.\n' +
pexpect.ExceptionPexpect(pexpect.EOF).get_trace())
输出:
Warning: Permanently added '192.168.x.x' (RSA) to the list of known hosts.
someuser@192.168.x.x's password: correctpassword
Linux ********** Thu Apr 10 13:58:00 UTC 2008 i686
The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.
To access official Ubuntu documentation, please visit:
http://help.ubuntu.com/
You have mail.
Last login: Tue Dec 14 20:17:52 2021 from 192.168.x.x
someuser@192.168.x.x:~$ df -h
df -h
Filesystem Size Used Avail Use% Mounted on
...
/dev/sda1 228M 25M 192M 12% /boot
someuser@192.168.x.x:~$ lshw
lshw
WARNING: you should run this program as super-user.
...
configuration: driver=ahci latency=64 module=ahci
someuser@192.168.x.x:~$ sudo ls /
sudo ls /
bin dev ...
cdrom home lib mnt proc srv usr
someuser@192.168.x.x:~$ exit
exit
logout
Connection to 192.168.x.x closed.
Process finished with exit code 0