前幾天發現網站打不開,提示資料庫連接錯誤,我登入linux 發現mysqld服務不知道什麼時候停止了。幸好我即使發現。
於是決定寫一個shell指令碼每分鐘自動檢測mysqld服務,如果探索服務沒起來就自動啟動mysqld服務
也就是:通過cron定時任務執行檢測指令碼
編寫檢測指令碼 /root/bin/check
代碼如下 |
複製代碼 |
#!/bin/bash check=`pgrep mysql` if [ -n "$check" ]; then exit else date=$(date +"%Y-%m-%d %H:%M:%S") /etc/init.d/mysqld start echo 'error: mysqld at ' $date fi |
明:也可以修改check=`pgrep mysql` 比如 check=`pgrep httpd` 或者 check=`pgrep nginx`來監測其他服務
編輯cron執行
crontab -e
cron內容如下,其中注釋掉了一行,可選擇性編寫
#* * * * * sh /root/bin/check > /dev/null 2>&1 #執行後不發送結果郵件
* * * * * sh /root/bin/check >> /root/bin/log.txt #執行後發送結果到指定檔案
由於cron每次執行後如果有輸出則會預設發送郵件到 /var/spool/mail/root 長時間會導致 此檔案有很多無用記錄
我們可以用 > /dev/null 2>&1 忽略結果寫入
當然也可以用 >> /root/bin/log.txt 寫入到指定檔案(要事先建立好檔案)
符:
cron命令列簡要說明
分 時 日 月 星期 命令列
例: */5 * * * * cmd #表示每5分鐘執行一次命令
command > filename 把標準輸出重新導向到一個新檔案中
command >> filename 把標準輸出重新導向到一個檔案中(追加)
command 1 > fielname 把標準輸出重新導向到一個檔案中
command > filename 2>&1 把標準輸出和標準錯誤一起重新導向到一個檔案中
command 2 > filename 把標準錯誤重新導向到一個檔案中
command 2 >> filename 把標準輸出重新導向到一個檔案中(追加)
command >> filename 2>&1 把標準輸出和標準錯誤一起重新導向到一個檔案中(追加)
command < filename >filename2 把command命令以filename檔案作為標準輸入,以filename2檔案作為標準輸出
command < filename 把command命令以filename檔案作為標準輸入
command << delimiter 把從標準輸入中讀入,直至遇到delimiter分界符
command <&m 把檔案描述符m作為標準輸入
command >&m 把標準輸出重新導向到檔案描述符m中
command <&- 把關閉標準輸入
command 2>&1 把command命令標準錯誤重新導向到標準輸出
下面的shell通過一個while-do迴圈,用ps -ef|grep 檢查loader進程是否正在運行,如果沒有運行,則啟動,這樣就保證了崩潰掛掉的進程重新被及時啟動。
必須注意兩點:
1、ps |grep 一個進程時必須加上其路勁,否則容易grep到錯誤的結果;
2、必須用 -v 從結果中去除grep命令自身,否則結果非空。
代碼如下 |
複製代碼 |
#!/bin/sh #===================== #YuanHui.HE #khler@163.com #===================== while : do echo "Current DIR is " $PWD stillRunning=$(ps -ef |grep "$PWD/loader" |grep -v "grep") if [ "$stillRunning" ] ; then echo "TWS service was already started by another way" echo "Kill it and then startup by this shell, other wise this shell will loop out this message annoyingly" kill -9 $pidof $PWD/loader else echo "TWS service was not started" echo "Starting service ..." $PWD/loader echo "TWS service was exited!" fi sleep 10 done |
如果啟動此shell時發現進程已經存在,說明以別的方式啟動了進程而不是此shell,那麼它會持續提醒找到進程,解決辦法是,要麼只用此shell啟動服務,要麼一經發現以其他方式啟動的服務即kill掉,上面的語句就是這麼乾的:
kill -9 $pidof $PWD/loader
再補充一個監控nginx的shell指令碼
Nginx 雖然處理並發量比 apache 確實要強點,但它這種 php-cgi 模式不是太穩定,這點網上也有朋友總結了,我在實現項目中也感受到了。
我們一台支付機,偶爾會出現以下情況的:php-cgi 進程突然消失了,造成PHP指令碼無法訪問;更不可思議的是明明是php-cgi 開啟有兩個連接埠在監聽的,莫名其秒的突然有一個php-cgi 的連接埠被關閉了,造成所有請求全積在一個連接埠上,
結果造成PHP指令碼訪問異常。
基本這種情況,我寫了個監控shell指令碼的解決方案,不管以上出現那種情況,都自動回復Nginx的服務.該指令碼在生產環境上運行正常:
代碼如下 |
複製代碼 |
#!/bin/bash # # filename: webservermonitor.sh # 功能:監控 nginx 的 php-cgi 是否正常 # 作者:V哥 # 運行: webservermonitor.sh & # # php-cgi 監聽的IP和連接埠 V_PHP_CGI_PORT="127.0.0.1:9000 127.0.0.1:9001" # nginx重啟的指令碼 V_NGINX="/usr/local/nginx/sbin/restart.sh" # 記錄檔 V_LOG="/tmp/webservermonitor.log" # 函數定義:重啟nginx function restart_nginx(){ echo "----- `date` -----" >> $V_LOG echo "------------------" >> $V_LOG echo "`ps aux |grep 'nginx'`" >> $V_LOG echo "------------------" >> $V_LOG echo "`ps aux |grep 'php-cgi'`" >> $V_LOG echo "------------------" >> $V_LOG echo "`netstat -nlpt | grep 'php-cgi'`" >> $V_LOG echo "------------------" >> $V_LOG $V_NGINX >> $V_LOG } # 迴圈執行,不採用 crontab ,國為 crontab 最小單位是分鐘,時間太長了 while : do # 1:先檢測 nginx 主進程是否存在 V_NGINX_NUM=`ps axu |grep 'nginx' |grep -v 'grep' |wc -l` if [ $V_NGINX_NUM -lt 1 ];then restart_nginx continue fi # 2:再檢查php-cgi是否有進程存在 V_PHP_CGI_NUM=`ps axu |grep 'php-cgi' |grep -v 'grep' |wc -l` if [ $V_PHP_CGI_NUM -lt 1 ];then restart_nginx continue fi # 3:再判斷連接埠是否正常 for PORT in $V_PHP_CGI_PORT do V_NUM=`eval "netstat -nlpt | grep '${PORT}' | wc -l"` if [ $V_NUM -lt 1 ];then restart_nginx continue fi done # 休眠 sleep 5 done |
ps:當然現在有一些伺服器也提供方法像dnspod就提供了網域名稱監控功能,可以監控到伺服器是否正常哦。