Linux 使用 monit 監控程序運行

1. 測試環境

Ubuntu 18.04
內核:55.0.0.36-generic

2. 安裝軟件

apt-get install monit
該程序會開機自動運行。
該程序幫助文檔:
https://mmonit.com/monit/documentation/monit.html

3. monit配置文件

vim /etc/monit/monitrc
第19行左右:
set daemon 120
這裏默認是120s,表示每120秒檢查一下被監視的程序狀態。可以改小一點。例如,改成6啥的。
啓用web服務,在第159行左右:

    set httpd port 2812
	use address localhost
	allow localhost
	allow admin:monit

至少去掉上面四行註釋。這樣,啓動服務後,它會自動在後臺運行http服務,顯示各程序狀態。這裏是默認配置,即在瀏覽器打開 localhost:2812 就可以訪問,而登錄時,賬號是admin,密碼是monit

4. monit服務啓動與停止

每次修改完配置文件後,若要新配置生效,必須重啓monit服務。
重啓命令:systemctl restart monit
停止命令:systemctl stop monit
啓動命令:systemctl start monit
查看當前服務狀態:systemctl status monit
如果啓動後,報錯,提示不能啓動,往往是配置文件寫錯了。使用查看當前服務狀態命令,可以看到是哪裏寫錯了。
注意:此服務會開機自啓動。

5. 關閉或開啓開機自啓動

關閉開機自啓動:systemctl disable monit
開啓開機自啓動:systemctl enable monit
注:當程序正在後臺運行時,關閉開機自啓動操作,並不會關閉在後臺運行的那個進程。

6. 查看monit的日誌

默認日誌存放位置爲/var/log/monit.log,此位置似乎可在上述配置文件中配置。

7. 如何監控自己的程序(當看門狗使用)

此處爲示例。
需求:有一個待監視的程序,需要保證它一直在執行,不論是正常退出,還是出現segmentation fault 等情況導致退出,需要將其重啓。
思路:寫一個腳本,檢查程序是否還在,不在就啓動它。然後利用monit定時執行的功能,定時調用這個腳本進行檢查即可。

(1) 待監控的程序示例

該示例程序如下:
程序名 Watched.cpp

#include <iostream>
#include <thread>
using namespace std;

#include <unistd.h>
#include <stdlib.h>
#include <time.h>

void raiseSegmentationFault(void)
{
    cout << "Segmentation Fault Exit." << endl;
    int *p = 0; // emtpy pointer.
    *p = 0;
}

int main()
{
    cout << "Start Watched..." << endl;

    srand(time(NULL));
    int a = rand();
    bool raiseFlag = a % 2 == 0;
    if (raiseFlag)
    {
        cout << "It will raise a segmentation fault after sleep." << endl;
    }
    else
    {
        cout << "It will normal exit after sleep." << endl;
    }

    int t = 10;
    while (t--)
    {
        cout << "Sleep " << t << "s" << endl;
        sleep(t);
    }
    
    if (raiseFlag)
    {
        // raise segment fault by random.
        raiseSegmentationFault();
    }
    cout << "Normal Exit." << endl;
    return 0;
}

該程序說明:此程序大約會在45秒後自動退出。但通過隨機數控制,退出時狀態有兩種,每次退出時,各有一半概率選中,一種是正常執行完畢而退出,另一種是segmentation fault(通過操作空指針引發的異常)退出。
現在需要此程序需要一直在運行,不論是正常退出,還是segmentation fault 引起的退出,都應該將其再次啓動。
使用g++正常編譯此程序即可,例如 g++ Watched.cpp -o Watched.out。
假設編譯後文件名爲Watched.out
文件存放路徑爲:/home/hehe/Desktop/project/Watched/
/home/hehe/Desktop/project/Watched/ 目錄結構如下:

  1. Watched.cpp
  2. Watched.out

(2) 檢查程序運行狀態的腳本

該腳本即是檢查程序是否還在,不在就啓動它。
該腳本如下:
腳本名 check.sh

#! /bin/bash 

Check_String="Watched.out"

Exclude_String="check.sh" 

Restart_Command="/bin/bash /home/hehe/Desktop/project/Watched/start.sh"

PROCESS=$(ps -ajx | grep $Check_String | grep -v grep | grep -v $Exclude_String)

# echo $PROCESS
if [ -n "$PROCESS" ];
then
	echo "Still Runing..."
else
	echo "Try Restart..."
	$Restart_Command
fi;

該腳本說明,利用ps命令查詢進程,並通過grep命令查詢指定字串代表的Watched.out程序是否存在。如果存在,則不進行操作。如果不存在,認爲Watched.out程序已退出,則進行啓動操作,請注意,腳本有超時執行時間,因此,檢查完後,腳本必須退出。
記得使用 chmod +x check.sh 加執行權限。
文件存放路徑爲:/home/hehe/Desktop/project/Watched/
/home/hehe/Desktop/project/Watched/ 目錄結構如下:

  1. Watched.cpp
  2. Watched.out
  3. check.sh

注:monit 是有root權限的,似乎該腳本及其啓動的程序也會獲得權限。

(3) 啓動程序的腳本

在check.sh中,如果沒有查到程序在啓動,則需要啓動它,此處是通過執行start.sh腳本使其啓動,請注意,腳本啓動程序後,該腳本必須退出,否則會導致check.sh無法退出。
該腳本名:start.sh

#! /bin/bash -x
export DISPLAY=:0.0
cd /home/hehe/Desktop/project/Watched
#sudo gnome-terminal -- bash -c "./Watched.out;exec bash;"
sudo gnome-terminal -- bash -c "./Watched.out;"

該腳本說明,首先進入到相應的目錄,然後新建一個終端,在終端中執行命令“./Watched.out;”,該腳本在新建終端後會自動退出,而終端會一直存在,直到Watched.out退出後退出,但如果後面加上“exec bash;”,則這個新終端在Watched.out退出後不會自動退出。
記得使用 chmod +x start.sh 加執行權限。
文件存放路徑爲:/home/hehe/Desktop/project/Watched/
/home/hehe/Desktop/project/Watched/ 目錄結構如下:

  1. Watched.cpp
  2. Watched.out
  3. check.sh
  4. start.sh

(4) 修改配置文件

vim /etc/monit/monitrc
參照第299行左右的寫法,在文件中,加入如下兩行語句。

check program Watched with path /home/hehe/Desktop/project/Watched/check.sh timeout 5 seconds

if status != 0 then alert

配置說明:
program Watched,這個Watched是表示名字,在不衝突的情況,可以任意起名。後續在web頁面上,看到的就是這個名字。
path /home/hehe/Desktop/project/Watched/check.sh 這個路徑即是每次要執行的文件。
timeout 5 seconds,如果check.sh執行了5s還沒有執行完,則強行中斷check.sh。注意,這個時間不能配置爲負數。如果配置爲0了,那就基本等於每次檢查時都要中斷它了。
if status != 0 then alert,必須要配置這樣一句類似話,否則命令不完整。該句的status 是上一條shell命令退出的狀態碼,這裏即是check.sh執行的結果。
關於status說明,見其他博客,如 https://blog.csdn.net/wlovh1989/article/details/51113488/
還有,可在第19行左右,把每次檢查的時間改小一點,例如改成6秒
set daemon 6
在Web界面查看。
默認web界面網址是:localhost:2812。進入後,輸入默認賬號admin,和密碼monic
即可看到。

(5) 報錯解決

可能會報如下錯誤。
Unable to init server: Could not connect Connection refused Restart… # Failed to parse arguments: Cannot open display.
目前,發現是那句新建終端有問題。即用戶沒有圖形化界面,但嘗試去新建一個圖形化的終端。
修改方法
第一步,設置環境變量。
export DISPLAY=:0.0
這句可加在start.sh腳本執行新建終端命令之前。
第二步,
需要在終端執行一次這個命令,允許 本機(這裏只允許了local) 其它無圖形界面的用戶,連接當前圖形界面。該命令關機後失效。
xhost + local:
若要實現開機就能有這個功能,可以寫到開機自啓動文件中去。例如/etc/profile文件。
若要關閉,使用xhost -即可。
更多與該問題有關的內容,請參見:
https://www.x.org/archive/X11R6.8.1/doc/xhost.1.html
https://www.cnblogs.com/js1314/p/10373332.html
https://blog.csdn.net/u011728480/article/details/66974510
https://www.x.org/archive/X11R6.8.1/doc/xhost.1.html

(6) bug

在測試時,發現這個Watched.out程序啓動後,有時候不會退出,不知道是什麼鬼問題。定時函數出問題了?在沒有關閉Watched.out時,重啓monit後,會有一定機率觀察到Watched.out一直都沒有執行完。

(7) 其他提醒

請仔細檢查自己的check.sh等腳本程序,並且在本地充分測試,以防不對。
可以在配置文件第20行左右的位置,改成

set daemon 6 
	with start delay 50

即,啓動或重啓monit後,第一次會延遲50s後再檢查(可防止開機後立即執行造成問題),不開這個選項,會啓動monit後,立即檢查。然後是每6s定時檢查一次。
經測試,那個web服務可以不開,不影響監控程序。但在測試腳本時,開啓web服務比較方便。

8. 其他類似monit的程序

linux有crond的守護程序,但似乎只能精確到分。
其他的解決方案,如下文記錄的
https://www.cnblogs.com/Hackerman/p/3930505.html
https://www.cnblogs.com/Hackerman/p/3932058.html

9. 關於monit的參考鏈接

monit 官方手冊
https://www.cnblogs.com/jinjiangongzuoshi/p/3702752.html
https://blog.csdn.net/weixin_33859504/article/details/92009871
https://www.cnblogs.com/kevingrace/p/6322324.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章