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/ 目錄結構如下:
- Watched.cpp
- 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/ 目錄結構如下:
- Watched.cpp
- Watched.out
- 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/ 目錄結構如下:
- Watched.cpp
- Watched.out
- check.sh
- 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