2017-01-05 67 views
0

沒有運行按照git documentation後收到鉤基本上是塊回購,直到它完成:混帳後收到鉤背景

...客戶端不會斷開,直到它完成,所以如果您嘗試做任何可能需要很長時間的事情,請小心。

如果您需要掛鉤來啓動構建作業,然後在啓動另一個作業(如部署作業)之前輪詢完成作業,則會導致問題。例如,構建服務器無法在所述腳本運行時從回購站中獲取。

我們還假設您完全沒有能力將您的腳本放在git服務器上作爲shell命令執行,整個nohup /usr/bin/env python /path/to/post_receive.py 2>&1 > /dev/null &方法類似於this question

讓我們還假設你已經嘗試了整個雙os.fork()「荷蘭國際集團守護類似this和其他一些問題的過程(非工作如下示例代碼),發現混帳仍在等待長期運行的孩子在完成鉤子之前完成。

pid = os.fork() 
if pid == 0: 
    os.setsid() 
    pid = os.fork() 
    if pid == 0: 
     long_running_post_receive_function() 
    else: 
     os._exit(0) 
else: 
    for fd in range(0, 3): 
     os.close(fd) 
    os._exit(0) 

因此,有了這些限制,任何人都可以使用長時間運行的python post-receive hook來成功實現在後臺運行而不會阻止回購嗎?

編輯

工作最小的結構也不例外處理......感謝@torek和@jthill

pid = os.fork() 
if pid == 0: 
    os.setsid() 
    pid = os.fork() 
    if pid == 0: 
     for fd in range(0, 3): 
      os.close(fd) 
     long_running_post_receive_function() 
    else: 
     os._exit(0) 
else: 
    sys.exit() 
+0

您也可以使用某種生產者/消費者模型,其中post-receive鉤子發送某種「異步消息」(可能與觸摸文件一樣簡單),這會導致消費者守護程序注意這一點,並開展工作。 – Mort

+0

我當然同意,這是一個替代方案,它實際上打敗了我試圖完成的目標 –

+1

我很累,但它看起來像你在做你的dup2()錯誤的地方。在長期運行的過程中,fd仍然是開放的。 – jthill

回答

2

您需要關閉所有的描述符的訪問,使SSH知道它永遠不會獲得更多的數據。換句話說,在描述符0到2上調用os.close。實際上,您需要那些爲開放雖然,所以最好打開os.devnullos.dup2結果描述符超過0,1和2(對於真正健壯的軟件,請確保os.open當然沒有返回值0 <= fd <= 2,如果是的話,沒關係,只要保留它就可以了,而其他的則重複)。 (你還需要通常的雙叉竅門,這可能是明智的,以消除會話ID等等。在一些Unix衍生系統中有一個庫例程daemon,它可能是libc或libutil ,它爲你做了所有這些,一些細節不可避免地取決於操作系統,比如放棄控制終端的方式(如果有的話)。但是,你的鏈接Python特定答案中缺少的主要東西是替換stdin/stdout/stderr描述符)。

+0

除非我犯了一個錯誤或者遺漏了某些東西,這似乎仍然不起作用。我用我試過的一個樣本編輯了我的問題。 –

+0

工作最小結構添加...謝謝! –