2009-12-05 58 views
0

我有幾個服務器和其他守護進程需要以正確的順序啓動。如何在Ubuntu下對init.d腳本進行排序

我從骨架腳本創建的init.d腳本,並可以將它們安裝使用編號命名系統以正確的順序啓動,但一些問題依然存在:

一臺服務器(「serverA的」)需要初始化數據庫連接,然後在套接字上偵聽。 然後,另一個服務器('serverB')需要連接到該套接字,並且如果先前的過程尚未偵聽,則連接將失敗。有沒有辦法阻止serverA的init.d腳本終止直到serverA開始監聽?在serverA init終止之前,serverB init不會啓動。

現在,安裝程序的工作原理是讓serverB重新嘗試連接,直到成功爲止,但該方法似乎很脆弱。我希望更強烈地瞭解如何強制排序。

回答

3

是的,這是我的問題,我正在回答,但我發現這種技術是有用的,並且正在與其他人共同努力解決類似問題。

我發現socat在等待套接字或端口時非常有用。像的init.d腳本:

case 「$1″ in 
    start) 
    echo '--benign phrase' | socat - UNIX-CONNECT:/path/to/socket,retry=10,intervall=1 
;; 

會等到插座變爲可寫,然後返回。不涉及守護進程,因此它會阻止執行更高編號的init.d腳本,直到完成。

使用這樣的服務器腳本將會減慢啓動順序,因此是非最優的,但是對於在腳本中散佈'sleep n'語句的非常脆弱的方法來說,這是一個很大的改進。

2

我不認爲它是脆弱的 - 至少我可以想象它不會脆弱的場景。重試時間爲5秒,並且一點都不差。它是一種KISS方法,並且沒有任何你不明白的角落案例。

獲得一個分佈式環境同步並不是因爲心臟不好,在你的例子中它的矯枉過正。

爲了讓你對自己的方法有一定的信心,我可以告訴你,我已經有數十個手工編寫的複雜服務器進程分佈在Web場中,即使數據庫服務器已經消失,他們也從來沒有給我任何傷心,網絡中繼線已經斷開等等,他們只是繼續運行在降級模式下,直到數據庫回來。

2

如果服務器在域套接字上偵聽,則可以構建一個輪詢該套接字的循環。有可能是在bash做到這一點更簡單的方法,但它可能看起來像:

for i in 1 2 3 4 5; do 
    if [ -e '/var/run/myserver.sock' ]; then 
    break 
    fi 
done 

另一個解決方案是在您的服務器不守護進程,直到它已經打開監聽套接字。這樣,init腳本將暫停,直到進程守護進程,這保證了套接字可用。

當然,這取決於您的應用程序本身進行守護進程,而不是通過其他方式。 ( 「在/ usr/bin中/ MYSERVER &」 等。)

更新時間:

還要注意的是,你現在正在做的是所有System-V風格的初始化。 Ubuntu實際上使用Upstart,這是一個基於事件的系統,而不是一系列腳本。你可以選擇使用暴發戶作業而不是System-V初始化腳本,並從你的服務器發起一個自定義的Upstart事件,這會觸發第二臺服務器的啓動。

Getting Started guide有一個例子在最底部。我不知道是否有API方式,但它可能只是一個「系統(」/ bin/initctl emit myevent「);」在您的第一臺服務器上正確的時間點。其他擁有更多新貴體驗的人可能可以更好地闡述/進一步闡述。

+0

我相信套接字'文件'總是存在,所以它的存在不是一個好的指標。延遲守護進程方法很有前途。我現在使用shell'&'方法(快速簡單),但是在內部進行守護進程非常實用。 – Rdbhost 2009-12-05 19:20:15

+0

您可以在啓動服務器之前刪除套接字,因此它將不得不重新創建它。 (我也忘了,循環可能也需要短暫的睡眠。) – 2009-12-05 19:56:20

+0

您可能需要在該輪詢循環中進行睡眠。 – mc0e 2015-02-17 13:09:08