2010-05-21 57 views
7

我正在使用Linux上的集羣系統(www.mosix.org),它允許我運行作業並讓系統在不同的計算機上運行它們。喬布斯是運行像這樣:如何識別Python中的進程ID

mosrun ls & 

這自然創造的過程,並在後臺運行,返回的進程ID,例如:

[1] 29199 

後就會回來。我正在編寫一個可以運行作業並控制它們的Python基礎結構。爲此,我想使用上述的mosrun程序運行作業,並保存產生的進程的進程ID(本例中爲29199)。這自然不能使用os.system或commands.getoutput來完成,因爲打印的ID不是打印輸出的內容......任何線索?

編輯

由於python腳本只是爲了最初運行腳本,腳本需要比Python Shell中運行的時間更長。我想這意味着mosrun進程不能是腳本的子進程。有什麼建議麼?

謝謝

+0

正常情況下,子進程在父進程死亡時繼續運行。 – 2010-05-21 21:05:06

回答

2

看起來像你想確保孩子的過程是daemonized -PEP 3143,我指出,它記錄並指向參考實現,並指向其他人。

一旦你的過程(仍在運行Python代碼)的進程化,不管是在PEP 3143或他人提供的手段,你可以os.execl(或其他os.exec...功能)目標代碼 - 這將運行該目標代碼準確我們剛纔所說的同一個過程是守護進程的,所以它可以根據需要繼續守護進程。

,因爲它需要在同一(進程化)進程中運行,覆蓋其可執行代碼的最後一步不能使用subprocess - 正是os.execl和朋友的。

第一步,系統守護進程之前,可能被認爲可以通過subprocess完成,但是這有點不方便(你需要把守護進程,然後-os.exec代碼在一個單獨的.py):最常見的你只是想os.fork並立即守護進程的子進程。

subprocess作爲一種大多數跨平臺的方式來運行其他進程是相當方便的,但它並不能真正替代Unix的高級用法(如在這種情況下的守護進程)的舊式「fork和exec」方法 - - 這就是爲什麼Python標準庫也允許你通過模塊os中的那些函數來執行後者是件好事! - )

+0

謝謝。我能否從舊進程中知道守護進程的進程ID? – 2010-05-23 18:17:32

+0

雙叉有一點問題,所以你需要進行通信 - 例如,子進程可能會在它的「stdout」(父進程可以從中獲得它)之後將它的進程標識寫入其「stdout」分叉之前和結束之前。但是,您需要爲此制定自己的協議,因爲標準Python庫中沒有建立一個協議。 – 2010-05-23 19:13:54

3

使用subprocess模塊。 Popen實例具有pid屬性。

+0

非常好 - 也在尋找這個 – wvd 2010-05-21 18:54:53

+0

這不就是說我的新進程會是python進程的兒子嗎?當我終止python進程時會發生什麼? (見編輯)。謝謝 – 2010-05-21 19:32:07

0

謝謝大家的幫助。這是我最後做的,似乎工作正常。該代碼使用python-daemon。也許應該做些關於將流程標識從孩子轉移到父親的更聰明的辦法,但這更容易。

import daemon 
def run_in_background(command, tmp_dir="/tmp"): 

    # Decide on a temp file beforehand 
    warnings.filterwarnings("ignore", "tempnam is a potential security") 
    tmp_filename = os.tempnam(tmp_dir) 

    # Duplicate the process 
    pid = os.fork() 


    # If we're child, daemonize and run 
    if pid == 0: 
     with daemon.DaemonContext(): 
      child_id = os.getpid() 
      file(tmp_filename,'w').write(str(child_id)) 
      sp = command.split(' ') 
      os.execl(*([sp[0]]+sp)) 
    else: 
     # If we're a parent, poll for the new file 
     n_iter = 0 
     while True: 
      if os.path.exists(tmp_filename): 
       child_id = int(file(tmp_filename, 'r').read().strip()) 
       break 

      if n_iter == 100: 
       raise Exception("Cannot read process id from temp file %s" % tmp_filename) 
      n_iter += 1 

      time.sleep(0.1) 

     return child_id