2013-12-10 268 views
19

我正在調試一些必須在我的虛擬機上運行的python腳本。而且,我更喜歡在本地編輯腳本(在虛擬機之外)。所以我發現它的每個時間都是虛擬機的修改後的腳本繁瑣的scp。任何人都可以建議一些有效的方式在遠程服務器上運行本地python腳本

特別是,我想知道是否有可能在遠程PVM上執行python腳本。類似的東西:

python --remote [email protected] hello.py //**FAKED**, served to explain ONLY 

回答

37

這是可能的使用ssh。 Python的接受連字符( - )作爲參數來執行標準輸入,

cat hello.py | ssh [email protected] python - 

運行蟒蛇--help獲取更多信息。

+0

難道你不能忽略'-'嗎?沒有,我可以很好地工作。 –

+1

如果代碼中的子模塊位於子文件夾中,該怎麼辦? –

+2

在這種情況下,你會在哪裏添加命令行參數? – ubundows

3

你可以通過SSH來做到這一點。

ssh [email protected] "python ./hello.py"

可以在SSH使用文本編輯器或X11轉發還可以編輯腳本。

+4

這執行遠程服務器上的_remote_ python腳本。據我所知,作者想要在遠程服務器上執行_local_ python腳本。 – Sney

+0

是的,你是對的。我建議通過ssh直接在遠程機器上進行編輯,以避免「上載階段」。 實際上,您可以上傳並執行一行文件(例如http://unix.stackexchange.com/a/57809)。但是這個解決方案對我來說看起來有點骯髒...... – smeso

25

雖然這個問題不是很新,並且已經選擇了答案,但我想分享一個很好的方法。

使用paramiko庫 - 純SSH的SSH2實現 - 您的python腳本可以通過SSH連接到遠程主機,將自身(!)複製到該主機,然後在遠程主機上執行該副本。遠程進程的stdin,stdout和stderr將在本地運行腳本中可用。所以這個解決方案几乎獨立於IDE。

在我的本地機器上,我使用一個cmd行參數'deploy'來運行腳本,這會觸發遠程執行。如果沒有這樣的參數,則運行用於遠程主機的實際代碼。

import sys 
import os 

def main(): 
    print os.name 

if __name__ == '__main__': 
    try: 
     if sys.argv[1] == 'deploy': 
      import paramiko 

      # Connect to remote host 
      client = paramiko.SSHClient() 
      client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
      client.connect('remote_hostname_or_IP', username='john', password='secret') 

      # Setup sftp connection and transmit this script 
      sftp = client.open_sftp() 
      sftp.put(__file__, '/tmp/myscript.py') 
      sftp.close() 

      # Run the transmitted script remotely without args and show its output. 
      # SSHClient.exec_command() returns the tuple (stdin,stdout,stderr) 
      stdout = client.exec_command('python /tmp/myscript.py')[1] 
      for line in stdout: 
       # Process each line in the remote output 
       print line 

      client.close() 
      sys.exit(0) 
    except IndexError: 
     pass 

    # No cmd-line args provided, run script normally 
    main() 

爲了簡化這個例子,省略了異常處理。在具有多個腳本文件的項目中,您可能必須將所有這些文件(以及其他依賴項)放在遠程主機上。

+0

我可以使用這個構造也作爲'with open paramiko.SSHClien()... '爲了避免忘記close()? – Mrlenny

+0

檢查len(sys.argv)> 1,否則腳本在遠程上崩潰。此外,遠程的bashrc(或shell初始配置)不得包含stdout上的任何打印(在bash中爲echo)。 –

0

在使用Paramiko之前,我想在運行已連接OpenVPN服務器的ssh服務器的主機上運行動態本地PyQt4腳本,並詢問其路由首選項(拆分隧道) )。

只要您連接的ssh服務器具有腳本所需的所有依賴關係(在我的情況下是PyQt4),您可以通過將其編碼爲base64並使用內置函數exec()輕鬆地封裝數據解碼的消息。如果我沒有記錯我的一行因爲這是:

stdout = client.exec_command('python -c "exec(\\"' + open('hello.py','r').read().encode('base64').strip('\n') + '\\".decode(\\"base64\\"))"')[1] 

這是很難讀,你必須逃離轉義序列,因爲它們(由接收器一旦被髮送者,然後再)解釋兩次。它也可能需要一些調試,我把我的服務器打包到PCS,或者我只是參考我的OpenVPN路由腳本。

這樣做與傳送文件不同的是,它不會觸及服務器上的磁盤,並且直接從內存中運行(除非它們記錄命令)。你會發現這種封裝信息(雖然效率低下)可以幫助你將數據打包成單個文件。例如,您可以使用此方法在主腳本中包含來自外部依賴關係(即圖像)的原始數據。

相關問題