2010-06-16 31 views
1

我正在使用ssh登錄到攝像機,scp tarball並從tarbal中提取文件,然後運行腳本。不過,我和Pexpect有問題。當壓縮包被複制時,Pexpect超時。似乎不等到它完成。然後它開始用untar命令做同樣的事情,我的代碼如下:使用pexpect的SCP tar文件

ssh_newkey = 'Are you sure you want to continue connecting'   
    copy = pexpect.spawn('ssh [email protected]') 
    i=copy.expect([ssh_newkey,'password:',pexpect.EOF]) 
    if i==0: 
     copy.sendline('yes') 
     i=copy.expect([ssh_newkey,'password:',pexpect.EOF]) 
    if i==1:   
     copy.sendline("service") 
     print 'Password Accepted' 
     copy.expect('[email protected]:') 
     copy.sendline('su - root') 
     i=copy.expect('Password:') 
     copy.sendline('root') 
     i=copy.expect('#') 
     copy.sendline('cd /tmp') 
     i=copy.expect("#") 
     copy.sendline('scp [email protected]:/home/user/tarfile.tar.gz .') 
     i=copy.expect([ssh_newkey,'password:',pexpect.EOF]) 
     if i==0: 
      copy.sendline('yes') 
      i=copy.expect([ssh_newkey,'password:',pexpect.EOF]) 
     else: 
      pass 
     copy.sendline('userpwd') 
     i=copy.expect('#') 
     copy.sendline('tar -zxvf tarfile.tar.gz bin/installer.sh') 
     i=copy.expect("#") 
     copy.sendline("setsid /tmp/bin/installer.sh /tmp/tarfile.tar.gz > /dev/null 2>&1 &")    
    elif i==2: 
     print "I either got key or connection timeout" 
    else: 
     pass 

任何人都可以幫助找到解決方案嗎?

感謝

+0

你可以關閉報價@的2DN線,所以它會打印更好? – 2010-06-16 14:51:48

回答

2

我不知道這是否是正確的,但我想嘗試的超時設置爲None

copy = pexpect.spawn('ssh [email protected]', timeout=None) 

根據源代碼,Pexpect的似乎不檢查超時當它被設置爲None

無論如何,即使我不確定它是否解決您的問題,我回答這個問題的原因是我想推薦使用paramiko代替。過去,我有很好的使用SSH通信的經驗。

+0

áš - 我現在感覺有點傻,我從來沒有想到這一點。超時設置爲30秒,tarbal需要比複製時間更長的時間。這項工作現在。感謝+1 – chrissygormley 2010-06-16 15:51:22

1

你有使用pexpect甚至paramiko的原因嗎?

,如果你設置一個public/private鍵,然後你可以作爲一個例子使用:

command = "scp [email protected]:/home/user/tarfile.tar.gz" 
split_command = shlex.split(command) 
subprocess.call(split_command) 

然後按照上面的paramiko使用的建議發送命令。

可以使用密鑰文件對於還有:

下面的類方法會給你一個持久的會話(雖然它是未經測試):

#!/usr/bin/python 
# -*- coding: utf-8 -*- 

from __future__ import print_function 
import os 
from paramiko import SSHClient, AutoAddPolicy, AuthenticationException, RSAKey 
from subprocess import call 

class CommsSuite(object): 

    def __init__(self): 
     self.ssh_client = SSHClient() 

     #-------------------------------------- 

     def _session_send(command): 
      """ 
      Use to send commands over ssh in a 'interactive_session' 
      Verifies session is present 
      If the interactive_session is not present then print the failed command. 

      This may be updated to raise an error, 
      which would probably make more sense. 

      @param command: the command to send across as a string 

      ::TODO:: consider raise exception here as failed 
         session will most likely be fatal. 

      """ 

      if self.session.send_ready(): 
       self.session.send("%s\n" % command) 
      else: 
       print("Session cannot send %s" % command) 

     #-------------------------------------- 

     def _get_persistent_session(_timeout = 5): 
      """ 
      connect to the host and establish an interactive session. 

      @param _timeout: sets the timout to prevent blocking. 

      """ 
      privatekeyfile = os.path.expanduser('~/.ssh/id_rsa')#this must point to your keyfile 

      private_key = RSAKey.from_private_key_file(privatekeyfile) 
      self.ssh_client.set_missing_host_key_policy(AutoAddPolicy()) 

      self.ssh_client.connect(hostname, 
            username = <username>, 
            pkey = private_key, 
            timeout = _timeout) 

      self.transport = self.ssh_client.get_transport() 
      self.session = self.transport.open_session() 
      self.session.exec_command("bash -s") 

     _get_persistent_session() 


     # build a comma seperated list of commands here as a string "[a,b,c]" 
     commands = ["tar -zxvf tarfile.tar.gz bin/installer.sh", "setsid /tmp/bin/installer.sh /tmp/tarfile.tar.gz > /dev/null 2>&1"] 
     # then run the list of commands 
     if len(commands) > 0: 
      for command in commands: 
       _session_send(command) 

     self.session.close()#close the session when done 


CommsSuite()