2012-05-24 151 views
10

我是新的python。我寫了一個腳本來連接到主機,並執行一個命令python paramiko ssh

ssh = paramiko.SSHClient() 
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
ssh.connect(host, username=user, password=pw) 

print 'running remote command' 

stdin, stdout, stderr = ssh.exec_command(command) 
stdin.close() 

for line in stdout.read().splitlines(): 
    print '%s$: %s' % (host, line) 
    if outfile != None: 
     f_outfile.write("%s\n" %line) 

for line in stderr.read().splitlines(): 
    print '%s$: %s' % (host, line + "\n") 
    if outfile != None: 
     f_outfile.write("%s\n" %line) 

ssh.close() 

if outfile != None: 
    f_outfile.close() 

print 'connection to %s closed' %host 

except: 
    e = sys.exc_info()[1] 
    print '%s' %e 

工作正常時,則遠程命令不需要TTY。我發現一個invoke_shell示例Nested SSH session with Paramiko。我對這個解決方案並不滿意,因爲如果一個服務器有一個未在我的腳本中指定的提示 - >無限循環或腳本中的指定提示是返回文本中的字符串 - >並非所有數據都會被接收。有沒有更好的解決方案,可能在哪裏stdout和stderr發回像我的腳本?

回答

11

有你可以找到大量的paramiko API文檔:http://docs.paramiko.org/en/stable/index.html

我用下面的方法來密碼保護的客戶端上執行命令:

import paramiko 
import sys 

nbytes = 4096 
hostname = 'hostname' 
port = 22 
username = 'username' 
password = 'password' 
command = 'ls' 

client = paramiko.Transport((hostname, port)) 
client.connect(username=username, password=password) 

stdout_data = [] 
stderr_data = [] 
session = client.open_channel(kind='session') 
session.exec_command(command) 
while True: 
    if session.recv_ready(): 
     stdout_data.append(session.recv(nbytes)) 
    if session.recv_stderr_ready(): 
     stderr_data.append(session.recv_stderr(nbytes)) 
    if session.exit_status_ready(): 
     break 

print 'exit status: ', session.recv_exit_status() 
print ''.join(stdout_data) 
print ''.join(stderr_data) 

session.close() 
client.close() 
+1

,而不是'data_block'應該使用'session.recv(4096)'和'session.recv_stderr(4096)'例如(在哪裏了'data_block'來嗎?)。 –

+0

你是對的,data_block就像你描述的那樣(recv/recv_stderr),但是我意外刪除了這些行。 – ThePracticalOne

+0

截至2015年5月,Paramiko文檔是[here](http://docs.paramiko.org/en/1.15/index.html) – Jeremiah

7

也有一些是錯誤的接受的答案,它有時(隨機)從服務器帶來一個限幅響應。我不知道爲什麼,我沒有調查接受的答案的錯誤原因,因爲這個代碼工作完美的我:

import paramiko 

ip='server ip' 
port=22 
username='username' 
password='password' 

cmd='some useful command' 

ssh=paramiko.SSHClient() 
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
ssh.connect(ip,port,username,password) 

stdin,stdout,stderr=ssh.exec_command(cmd) 
outlines=stdout.readlines() 
resp=''.join(outlines) 
print(resp) 

stdin,stdout,stderr=ssh.exec_command('some really useful command') 
outlines=stdout.readlines() 
resp=''.join(outlines) 
print(resp) 
+0

我也看到了這一點,它像一個競爭條件w/exit_status_ready()和recv_ready() – robert

0

@ThePracticalOne的代碼是偉大的展示除了一件事用法: Somtimes輸出將是不完整的。(session.recv_ready()成真的話後if session.recv_ready():session.recv_stderr_ready()session.exit_status_ready()進入下一個循環之前關真)

所以我的想法是檢索數據時,它已準備好退出會話。

while True: 
if session.exit_status_ready(): 
while True: 
    while True: 
     print "try to recv stdout..." 
     ret = session.recv(nbytes) 
     if len(ret) == 0: 
      break 
     stdout_data.append(ret) 

    while True: 
     print "try to recv stderr..." 
     ret = session.recv_stderr(nbytes) 
     if len(ret) == 0: 
      break 
     stderr_data.append(ret) 
    break