歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

在Hudson Job中啟動daemon進程

場景

在Hudson中新建一個Job用於構建Web工程,在Job的構建腳本的最後會啟動Jetty,觀察發現Jetty啟動之後一小段時間,進程就終止了。

環境

CentOS 6 x86_64,Hudson 3.0.1,Jetty 8,Oracle JDK 1.6

分析

剛開始在Job中啟動Jetty的方式是在Ant構建腳本build.xml中調用一個shell腳本進行應用部署和容器重啟。整個Job的構建過程正常,Jetty終止以後也查不到任何異常日志。

後來嘗試在Job的build step中直接使用"Execute shell"去調用shell腳本,發現Job的Console output出現如下提示:

Process leaked file descriptors. See http://wiki.hudson-ci.org/display/HUDSON/Spawning+processes+from+build for more information

查看上面的鏈接以及Google相關資料,發現Hudson在Job構建結束之後,kill所有未終止的衍生進程。

Hudson與子進程之間使用三根管道通信(stdin/stdout/stderr),這樣Hudson可以捕捉到子進程的輸出。由於子進程可能往stdout寫入大量數據然後立即退出,Hudson為了完整讀取子進程的輸出,會在用於子進程stdout的管道上等待EOF。這樣,無論子進程由於什麼原因退出,系統將關閉進程使用的文件描述符,因而Hudson總是可以收到EOF。

但是當子進程A在後台fork出另一個進程B的時候(比如啟動一個daemon進程),情況就出現一些變化。由於進程B會繼承進程A的文件描述符,如果進程B沒有關閉這些描述符,即使進程A退出,這些描述符依然是打開的,Hudson將不會在相應管道上收到EOF。通常一個實現良好的daemon會關閉所有文件描述符以避免這個問題,但是總有一些實現沒有遵循這個規則。在舊版本的Hudson上,這個問題將導致Job無法結束,Hudson一直在等待EOF;新版本則會打印出上面的"leaked file descriptors"警告,然後Job構建過程繼續。

看來Jetty可能沒有關閉繼承的文件描述符,Hudson在Job構建過程結束後認為Jetty進程未終止,因而將其kill掉了。上述鏈接指向的Hudson wiki頁面上提到可以使用daemonize工具將程序作為實現良好的daemon進程運行以避免這個問題。

在Hudson另一wiki頁面上進一步描述了Hudson殺掉衍生進程的情況。Hudson在執行Job時會設置一系列環境變量,這些環境變量將被Job衍生出的進程繼承。Hudson在kill衍生進程的時候會查看進程的環境變量,如果找到它之前設置的環境變量,則將其殺掉。Wiki上給出了一個簡單的方法來避免進程被kill掉:修改Hudson設置的環境變量BUILD_ID的值,從而讓Hudson認為此進程不是由Job的構建過程衍生的。如:

BUILD_ID=dontKillMe /usr/apache/bin/httpd

另外,在此wiki上還提到可以在啟動Hudson的時候通過Java選項來關閉Hudson殺掉所有衍生進程的這個功能:

java -Dhudson.util.ProcessTreeKiller.disable=true -jar hudson.war

解決方案

1.安裝daemonize包,使用daemonize命令wrap Jetty的啟動指令。

daemonize ${jetty_bin} start

2.在啟動Jetty之前,修改BUILD_ID環境變量。

# set BUILD_ID, or Hudson will kill any child processes

# that are started by build steps.

BUILD_ID="dontKillMe"

${jetty_bin} start


3.設置Java選項hudson.util.ProcessTreeKiller.disable為true。

Copyright © Linux教程網 All Rights Reserved