2011-08-09 115 views
5

我是一個新的paramiko用戶,並且在使用paramiko在遠程服務器上運行命令時遇到困難。我想導出一個路徑,並在後臺運行一個名爲tophat的程序。我可以用paramiko.sshclient()登錄,但我的代碼爲exec_command沒有結果。基本paramiko exec_command幫助

stdin, stdout, sterr = ssh.exec_command('export PATH=$PATH:/proj/genome/programs 
/tophat-1.3.0/bin:/proj/genome/programs/cufflinks-1.0.3/bin:/proj/genome/programs/ 
bowtie-0.12.7:/proj/genome/programs/samtools-0.1.16') 

stdin, stdout, sterr = ssh.exec_command('nohup tophat -o /output/path/directory -I 
10000 -p 8 --microexon-search -r 50 /proj/genome/programs/bowtie-0.12.7/indexes 
/ce9 /input/path/1 /input/path/2 &') 

沒有nohup.out文件和python只是去與任何錯誤消息的下一行。我也試過沒有nohup以及結果是一樣的。我試圖按照this paramiko tutorial

我錯誤地使用exec_command

+1

第二個命令運行在與第一個命令不同的shell中,所以'export'將不起作用。 –

+1

你最好把環境變量放在一行中。即:'ssh.exec_command('PATH =/bin:/ usr/bin:etcetera nohup ...')';這將只爲單個命令導出它,這正是你想要的。 –

回答

5

exec_command()是非阻塞的,它只是發送命令到服務器,然後Python將運行下面的代碼。

我認爲你應該等待命令執行結束,然後完成剩下的工作。

「time.sleep(10)」可以幫助,這需要「導入時間」。 一些示例顯示,您可以從stdout ChannelFile對象讀取,或者乾脆使用stdout.readlines(),它似乎讀取來自服務器的所有響應,猜測這可能有所幫助。

你的代碼,上面兩行exec_command,它們實際上是在不同的exec會話中運行。我不確定這是否會對您的情況產生一些影響。

我建議你看看演示文件夾中的演示,它們使用Channel類,它有更好的API來爲shell和exec進行阻塞/非阻塞發送。

+0

我有一個類似的問題,我只是想和我說stdout.readlines()對我很好。它迫使我的腳本等待exec_command()完成運行後再繼續。謝謝! – riggspc

0

這對我來說是封鎖的。

stdin, stdout, stderr = ssh.exec_command('sleep 10; hostname') 

這回

+2

如果您嘗試讀取輸出,則會阻止它。 – piyo

0

你最好在運行命令之前,加載在.bash_profile之前等待10秒。否則,您可能會收到'command not found'異常。

例如,我寫的命令command = 'mysqldump -uu -pp -h1.1.1.1 -P999 table > table.sql'在傾倒MySQL表

然後,我有到傾倒命令之前通過鍵入. ~/.profile; .~/.bash_profile;手動加載.bash_profile中的目的。

my_command = 'mysqldump -uu -pp -h1.1.1.1 -P999 table > table.sql;' 

pre_command = """ 
. ~/.profile; 
. ~/.bash_profile; 
""" 

command = pre_command + my_command 

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

我也遇到同樣的問題,看着this articlethis answer後,我看到的解決辦法是調用通道的recv_exit_status()方法。這裏是我的代碼:

import paramiko; 
import time; 

cli = paramiko.client.SSHClient(); 
cli.set_missing_host_key_policy(paramiko.client.AutoAddPolicy()); 
cli.connect(hostname="10.66.171.100", username="mapping"); 
stdin_, stdout_, stderr_ = cli.exec_command("ls -l ~"); 
# time.sleep(2); # Previously, I had to sleep for some time. 
stdout_.channel.recv_exit_status(); 
lines = stdout_.readlines(); 
for line in lines: 
    print line; 

cli.close(); 

現在我的代碼將被阻止,直到遠程命令完成。這種方法解釋here,請注意警告。