2013-10-15 15 views
0

這個問題是這個問題的後續:Using paramiko to send commands to an open shell that has an interactive element所以請在這裏回答之前閱讀。用交互式元素實現paramiko的超時

我已經成功地將數據發送到數組的系統shell,但是我需要幫助瞭解如何在數組花費太長時間來運行我發送的腳本時執行超時。 Paramiko的exec_command有一個timeout=參數,但這不會有幫助,因爲我發送的唯一命令是"script",它立即返回並等待通道上的輸入,並且當我嘗試執行時似乎將該函數的其餘部分打破爲沒有從陣列返回。

該陣列然後應該處理我發送它的腳本,並通過stdout返回輸出,但是,如果數組需要很長時間,我沒有辦法超時連接,它阻止了其餘的劇本。

這裏是我的代碼:

def run_script(self, script_name): 
    """ Run a script on the remote array and return the stdout 
    """ 
    try: 
     common_functions_file = os.path.join(SCRIPT_DIR, 'zfs_common_functions.js') 
     common_functions = open(common_functions_file).read().splitlines() 
     # add common_functions to the top of the script 
     script_contents = common_functions + open(script_name).read().splitlines() 
     stdin, stdout, stderr = self._ssh.exec_command('script') 
     for line in script_contents: 
      # Skip lines with comments 
      if re.match("^//", line): 
       continue 
      stdin.write(line) 
      stdin.write('\n') 
     stdin.write('.\n') 
     stdin.flush() 
     error = stderr.readlines() 
     if len(error) == 0: 
      try: 
       output = ''.join(stdout.readlines()) 
       if(re.search('aksh', output)): 
        logger.warn("ZFS Shell Error: %s" % output) 
        return None 
       return output 
      except Exception as e: 
       logger.exception(e) 

     else: 
      logger.error(error) 
      return None 
    except paramiko.SSHException as e: 
     logger.warn(
      "Couldn't execute script on array %s: %s" % (array.name, e)) 

    except AttributeError as e: 
     logger.exception(e) 
     raise 

    except Exception: 
     raise 

回答

2

我結束了與渠道,你可以在設置超時直接交互解決它:

def run_script(self, script_name): 
    """ Run a script on the remote array and return the stdout 
    """ 
    try: 
     chan = self._ssh.get_transport().open_session() 
     # five minute timeout on the channel communication 
     chan.settimeout(5*60.0) 
     common_functions_file = os.path.join(SCRIPT_DIR, 'zfs_common_functions.js') 
     common_functions = open(common_functions_file).read().splitlines() 
     # add common_functions to the top of the script 
     script_contents = common_functions + open(script_name).read().splitlines() 
     chan.exec_command('script') 
     if chan.send_ready(): 
      chan.sendall("\n".join(script_contents)) 
      chan.send("\n.\n") 

     results = StringIO() 
     error = StringIO() 
     bufsize = 1024 
     while not chan.exit_status_ready(): 
      if chan.recv_ready(): 
       data = chan.recv(bufsize) 
       while data: 
        results.write(data) 
        data = chan.recv(bufsize) 

      if chan.recv_stderr_ready(): 
       error_buf = chan.recv_stderr(bufsize) 
       while error_buf: 
        error.write(error_buf) 
        error_buf = chan.recv_stderr(bufsize) 

     exit_status = chan.recv_exit_status() 
     if exit_status == 0: 
      return results.getvalue() 
     else: 
      raise ZfsScriptError(results.getvalue()) 

    except socket.timeout: 
     logger.warn("%s: Timeout running %s" %(self.hostname, script_name)) 
     return None 

    except paramiko.SSHException as e: 
     logger.warn(
      "Couldn't execute script on array %s: %s" % (self.hostname, e)) 
     raise 

    except AttributeError as e: 
     logger.exception(e) 
     raise 

    except Exception: 
     raise 

    finally: 
     results.close() 
     error.close() 
     chan.close()