現在是讓 CruiseControl 運行了,但是還不能讓它在沒人參與的情況下運行。它目前在一個終端窗口中運行,所以需要讓 cruise 用戶永遠登錄,才能保持它一直運行。終端還是控制程序的唯一方式:可以按下 Ctrl+C 停止 CruiseControl,并再次運行程序重新啟動它。除非使用虛擬網絡計算(VNC)會話或類似的東西,否則就不能遠程地做上面這些事。如果 CruiseControl(或者 JVM)崩潰,就需要手動地重啟它。而且當重新啟動機器時,也需要手動地建立新會話、創建終端、再次啟動程序,CruiseControl 才能重啟。所以需要讓 CruiseControl 作為一個服務運行,或者用 Unix 的術語來說,作為一個 守護程序 運行。
讓程序在 Linux 下持續運行的方法有許多種。最常用的方法可能是把合適的腳本掛上 init
系統初始化進程,在系統啟動時啟動程序。這些腳本可以啟動和停止程序,但是不能在程序出現故障時自動重啟程序。
我用的方法 I 是下載并安裝 Daniel J. Bernstein 的 daemontools
(請參閱 參考資料)。這是一個小的程序包,負責啟動一組服務并保持這些服務一直運行。要執行自己的 daemontools
安裝,需要登錄為 root:
[root@fcvm ~]# mkdir -p /package [root@fcvm ~]# chmod 1755 /package [root@fcvm ~]# cd /package [root@fcvm package]# wget -q http://cr.yp.to/\ daemontools/daemontools-0.76.tar.gz [root@fcvm package]# gunzip daemontools-0.76.tar.gz [root@fcvm package]# tar -xpf daemontools-0.76.tar [root@fcvm package]# rm daemontools-0.76.tar rm: remove regular file 'daemontools-0.76.tar'? y [root@fcvm package]# |
要讓這個包能夠在 Fedora Core 4 上干凈地構建,必須對包的 C 源代碼稍做調整。請用文本編輯器,把 src/error.h 的第 6 行從 extern int errno;
改成 #include <errno.h>
。下面是使用 ed
的處理方法:
[root@fcvm package]# cd admin/daemontools-0.76 [root@fcvm daemontools-0.76]# ed src/error.h 595 6 extern int errno; c #include <errno.h> . wq 596 [root@fcvm daemontools-0.76]# |
現在可以完成安裝了:
[root@fcvm daemontools-0.76]# package/install Linking ./src/* into ./compile... Compiling everything in ./compile... [...] Creating /service... Adding svscanboot to inittab... init should start svscan now. [root@fcvm daemontools-0.76]# ps -ef | grep svs root 21160 1 0 16:09 ? 00:00:00 /bin/sh /command/svsca nboot root 21162 21160 0 16:09 ? 00:00:00 svscan /service root 21173 20051 0 16:10 pts/1 00:00:00 grep svs [root@fcvm daemontools-0.76]# |
daemontools
提供了叫作 svscan
的守護進程,它負責管理服務集合。每個服務都由 /service 目錄中的一個目錄代表,所以需要在這里為 CruiseControl 服務創建一個目錄。對于 /service 中的每個子目錄,svscan
都啟動一個子進程,運行 supervise
程序。
supervise
是負責管理 CruiseControl 這樣的獨立服務的程序。它創建子進程,運行服務子目錄中的 run
(例如 /service/cruisecontrol/run),從而啟動服務。如果子進程中止,supervise
會重新啟動它。supervise
也可以向子進程發送信號,停止或重新啟動子進程。
daemontools
還提供了兩個機制,負責處理它管理的服務的日志記錄。首先,叫作 readproctitle
的程序捕捉寫入標準錯誤流(在 Java 世界中,是 System.err
)的輸出并把輸出拷貝到一個小緩沖區中,這個小緩沖區是 ps
命令顯示的進程標題的一部分:
[root@fcvm daemontools-0.76]# ps -ef | grep proctitle
root 25040 25037 0 20:58 ? 00:00:00 readproctitle service
errors: ..............................................................
......................................................................
......................................................................
......................................................................
......................................................................
..........................................................
root 25047 24006 0 20:59 pts/1 00:00:00 grep proctitle
[root@fcvm daemontools-0.76]# |
在啟動時,緩沖區被初始化為包含點號,但是在出現錯誤時就被錯誤信息替代。這個機制對于少量信息(例如關鍵錯誤信息)來說很好。但是緩沖區尺寸小造成它不適合更大數量的日志信息,而且記錄的信息不能保存到磁盤也使得難以分析一段時間內的性能。daemontools
提供了第二種機制 —— multilog
程序,它負責這種大量日志。第二種機制在命令行參數輸出的指令控制下,把自己標準輸入中的行寫入日志文件。它包含對日志輪轉的控制,日志輪轉可以保持定量的日志信息,以使存儲空間不會耗盡。例如,multilog /home/cruise/log
這個簡單的命令就可以把信息記錄到 /home/cruise/log 目錄中的文件,當日志文件的尺寸達到 99,999 個字節時就輪轉日志文件,并保持 10 個舊的日志文件。
multilog
也由 supervise
管理,就像其他服務一樣。在 svsccan
發現的每個目錄中,它都會查找叫作 log 的子目錄,并創建一個 supervise
進程來管理這個目錄下 run
腳本的執行。它還安排一個管道,把主服務的標準輸出作為日志進程的標準輸入。
那么,要讓 daemontools
管理 CruiseControl,需要做什么呢?必須為這個服務和它的 multilog
伙伴創建目錄結構。還必須創建它們各自的 run
腳本,并為日志文件創建目錄。開始時,把服務目錄命名為 .cruisecontrol。前導點號會讓 svscan
忽略這個目錄,從而可以在第一次啟動服務之前進行設置:
[cruise@fcvm ~]$ mkdir -p log/cruisecontrol [cruise@fcvm ~]$ su - Password: [enter root password] [root@fcvm ~]# cd /service [root@fcvm service]# mkdir .cruisecontrol [root@fcvm service]# cd .cruisecontrol [root@fcvm .cruisecontrol]# mkdir log [root@fcvm .cruisecontrol]# |
然后,創建叫作 env 的目錄。要用這個目錄的內容設置 CruiseControl 的環境變量以及它要啟動的其他進程。在這里要確保 JAVA_HOME
有合適的值。在這里還要設置將要使用的構建工具需要的環境變量,例如 MAVEN_HOME
。
[root@fcvm .cruisecontrol]# mkdir env [root@fcvm .cruisecontrol]# cd env [root@fcvm env]# echo /usr/lib/jvm/java >JAVA_HOME [root@fcvm env]# echo /home/cruise/pkg/maven-1.0.2 >MAVEN_HOME [root@fcvm env]# ls JAVA_HOME MAVEN_HOME [root@fcvm env]# cd .. [root@fcvm .cruisecontrol]# |
清單 2 顯示了 /service/cruisecontrol/run 腳本:
清單 2. /service/cruisecontrol/run 的內容
#!/bin/sh svc=`pwd` cd /home/cruise exec 2>&1 exec setuidgid cruise \ envdir ${svc}/env \ java -jar pkg/cruisecontrol-2.2.1/main/dist/cruisecontrol.jar |
這個腳本相當簡單。它執行以下這些步驟:
- 保存服務目錄的名稱(在這個示例中是 /service/cruisecontrol)留待后用。
- 把當前目錄變為 /home/cruise。
- 讓標準錯誤流寫入到
multilog
進程的管道,這個管道已經連接到了標準輸出流。 - 啟動 JVM,運行 CruiseControl,以 cruise 這個用戶身份運行進程,并根據 /service/cruisecontrol/env 目錄中創建的文件設置環境。
清單 3 演示了 /service/cruisecontrol/log/run 腳本,它更簡單。它以 cruise 用戶的身份運行 multilog
:
清單 3. /service/cruisecontrol/log/run 的內容
#!/bin/sh exec setuidgid cruise multilog /home/cruise/log/cruisecontrol |
請注意,必須使用 chmod
把兩個腳本變成可執行的。而且,這兩個腳本都要小心地使用 exec
外殼命令,這個命令用一個程序替代另一個程序,但是沒有創建新進程。這一點很重要,因為 supervise
只能管理自己的直接子進程。如果沒有使用 exec
,那么 JVM 會作為執行 run 腳本的外殼的一個子進程啟動。如果向 supervise
發送了殺死其子進程的信息,那么外殼會接收到信號并退出,但是 JVM 會繼續運行,從而變成孤兒。supervise
并不會知道這一點,所以可能會接著啟動守護程序的第二個拷貝 —— 這并不是想要的結果。
在設置好服務目錄之后,可以把它改名,刪除前導點號。然后 svscan
就會自動啟動 CruiseControl,它的輸出也會出現在日志文件中:
[root@fcvm .cruisecontrol]# cd .. [root@fcvm service]# mv .cruisecontrol cruisecontrol [root@fcvm service]# cat /home/cruise/log/cruisecontrol/current [cc]Aug-24 21:45:45 Main - CruiseControl Version 2.2.1 [cc]Aug-24 21:45:46 trolController- projectName = [xstream] [cc]Aug-24 21:45:46 Project - Project xstream: reading settings from config file [/home/cruise/config.xml] [cc]Aug-24 21:45:47 BuildQueue - BuildQueue started [cc]Aug-24 21:45:47 Project - Project xstream starting [cc]Aug-24 21:45:47 Project - Project xstream: idle [cc]Aug-24 21:45:47 Project - Project xstream started [cc]Aug-24 21:45:47 Project - Project xstream: next build in 1 hours [cc]Aug-24 21:45:47 Project - Project xstream: waiting for next time to build [root@fcvm service]# |
文章來源于領測軟件測試網 http://www.kjueaiud.com/