在一个Python项目中,要执行“/usr/bin/sftp [email protected]”命令连接远程FTP服务器,代码如下:
_pass = 'assword:' _prompt = 'sftp> ' _newKey = "Are you sure you want to continue connecting (yes/no)?" self._client = pexpect.spawn(command_connect_sftp) match = [self._pass, self._newKey] i = self._client.expect(match) if i == 1: self._client.sendline("yes") self._client.expect(match) self._client.sendline(password) self._client.expect(self._prompt)
ERROR Internal system error occured handling command install for lidus2376 help Internal system error! Traceback (most recent call last): File "/usr/local/lib/python3.5/dist-packages/pexpect/expect.py", line 99, in expect_loop incoming = spawn.read_nonblocking(spawn.maxread, timeout) File "/usr/local/lib/python3.5/dist-packages/pexpect/pty_spawn.py", line 462, in read_nonblocking raise TIMEOUT('Timeout exceeded.') pexpect.exceptions.TIMEOUT: Timeout exceeded. During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/home/userbbauto/bbauto/src/bbautoserver.py", line 335, in _handle_api_install_request tgf_install = TgfInstall(self.input_params) File "/home/userbbauto/bbauto/src/tgfinstall.py", line 52, in __init__ debug=self.active_debug_groups, password=self.BBAUTO_PASSWORD) File "/home/userbbauto/bbauto/src/sftpconnection3.py", line 47, in __init__ i = self._client.expect(match) File "/usr/local/lib/python3.5/dist-packages/pexpect/spawnbase.py", line 321, in expect timeout, searchwindowsize, async) File "/usr/local/lib/python3.5/dist-packages/pexpect/spawnbase.py", line 345, in expect_list return exp.expect_loop(timeout) File "/usr/local/lib/python3.5/dist-packages/pexpect/expect.py", line 107, in expect_loop return self.timeout(e) File "/usr/local/lib/python3.5/dist-packages/pexpect/expect.py", line 70, in timeout raise TIMEOUT(msg) pexpect.exceptions.TIMEOUT: Timeout exceeded. command: /usr/bin/sftp args: ['/usr/bin/sftp', '[email protected]'] buffer (last 100 chars): b' NOT AN AUTHORIZED USER, PLEASE EXIT IMMEDIATELY\r\nConnected to ftp.ericsson.se.\r\nsftp> ' before (last 100 chars): b' NOT AN AUTHORIZED USER, PLEASE EXIT IMMEDIATELY\r\nConnected to ftp.ericsson.se.\r\nsftp> ' after: match: None match_index: None exitstatus: None flag_eof: False pid: 73 child_fd: 9 closed: False timeout: 30 delimiter: logfile: None logfile_read: None logfile_send: None maxread: 2000 ignorecase: False searchwindowsize: None delaybeforesend: 0.05 delayafterclose: 0.1 delayafterterminate: 0.1 searcher: searcher_re: 0: re.compile("b'assword:'") 1: re.compile("b'Are you sure you want to continue connecting (yes/no)?'")
分析发现异常的原因是expect()语句超时,期望得到的结果没有得到,直到超时抛出异常。
这是因为期望得到的结果只包含两种情况,一种是提示将FTP服务器加入到known_hosts中,另一种是提示输入密码。但是,由于当前机器上不检查hosts的公钥(避免了第一种提示),使用提前生成的私钥(避免了第二章提示),因而还有第三种可能,就是使用用户名和私钥直接连接FTP成功,从而得到了“ftp> ”的结果。
修改代码如下,解决该异常:
... match = [self._pass, self._newKey, self._promt] i = self._client.expect(match) if i==2: return if i==1: ...