使用process_monitor.sh監控hadoop進程的crontab配置
最後更新:2018-07-30
來源:互聯網
上載者:User
使用process_monitor.sh監控hadoop進程的crontab配置
可以從下列連結找到process_monitor.sh:
https://github.com/eyjian/mooon/blob/master/common_library/shell/process_monitor.sh
---------------------------------------------------------指令碼內容--------------------------------------------------------
#!/bin/sh
# https://github.com/eyjian/mooon/blob/master/common_library/shell/process_monitor.sh
# Created by yijian on 2012/7/23
#
# 作業記錄:/tmp/process_monitor.log,由於多進程同時寫,不一定完整,僅供參考。
# 請放到crontab中運行,如(注意要以後台方式運行,因為指令碼是常駐不退出的):
# * * * * * /usr/local/bin/process_monitor.sh /usr/sbin/rinetd /usr/sbin/rinetd > /dev/null 2>&1 &
#
# 進程監控指令碼,當指定進程不存在時,執行重啟指令碼將它拉起
# 特色:
# 1.本監控指令碼可重複執行,它會自動做互斥
# 2.互斥不僅依據監控指令檔名,而且包含了它的命令列參數,只有整體相同時互斥才生效
# 3.對於被監控的進程,可以只指定進程名,也可以包含命令列參數
# 4.不管是監控指令碼還是被監控進程,總是只針對屬於目前使用者下的進程
#
# 如果本指令碼手工運行正常,但在crontab中運行不正常,則可考慮檢查下ps等命令是否可在crontab中正常運行
# 實際中,遇到指令碼在crontab中運行時,找不到ls和ps等命令
# 原來是有些環境ls和ps位於/usr/bin目錄下,而不是常規的/bin目錄
export PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin:$PATH
trap "" SIGPIPE # 忽略SIGPIPE
# 需要指定個數的命令列參數
# 參數1:被監控的進程名(可以包含命令列參數)
# 參數2:重啟被監控進程的指令碼
if test $# -ne 2; then
printf "\033[1;33musage: $0 process_cmdline restart_script\033[m\n"
printf "\033[1;33mexample: /usr/local/bin/process_monitor.sh \"/usr/sbin/rinetd\" \"/usr/sbin/rinetd\"\033[m\n"
printf "\033[1;33mplease install process_monitor.sh into crontab by \"* * * * *\"\033[m\n"
exit 1
fi
process_cmdline="$1" # 需要監控的進程名,或完整的命令列,也可以為部分命令列
restart_script="$2" # 用來重啟進程的指令碼,要求具有可執行許可權
monitor_interval=2 # 定時檢測時間間隔,單位為秒
start_seconds=5 # 被監控進程啟動需要花費多少秒
cur_user=`whoami` # 執行本監控指令碼的使用者名稱
# 取指定網卡上的IP地址
#eth=1&&netstat -ie|awk -F'[: ]' 'begin{found=0;} { if (match($0,"eth'"$eth"'")) found=1; else if ((1==found) && match($0,"eth")) found=0; if ((1==found) && match($0,"inet addr:") && match($0,"Bcast:")) print $13; }'
# 下面這段指令碼,用來阻止多個監控指令碼進程出現
uid=`id -u $cur_user`
self_name=`basename $0`
self_cmdline="$0 $*"
process_name=$(basename `echo "$process_cmdline"|cut -d" " -f1`)
process_match="${process_cmdline#* }" # 只保留用來匹配的參數部分
process_match=$(echo $process_match) # 去掉前後的空格
# 用來做互斥,
# 以保證只有最先啟動的能運行,
# 但若不同參數的彼此不相互影響,
# 這樣保證了可同時對不同對象進行監控。
# 因為trap命令對KILL命令無效,所以不能通過建立檔案的方式來互斥。
active=0
# 記錄檔,可能多個使用者都在運行,
# 所以記錄檔名需要加上使用者名稱,否則其它使用者可能無許可權寫
log_filepath=/tmp/process_monitor-$cur_user.log
# 記錄檔大小(10M)
log_filesize=10485760
# 寫日誌函數,帶1個參數:
# 1) 需要寫入的日誌
log()
{
# 建立記錄檔,如果不存在的話
if test ! -f $log_filepath; then
touch $log_filepath
fi
record=$1
# 得到記錄檔大小
file_size=`ls --time-style=long-iso -l $log_filepath 2>/dev/null|cut -d" " -f5`
# 處理記錄檔過大
# 日誌加上頭[$process_cmdline],用來區分對不同對象的監控
if test ! -z "$file_size"; then
if test $file_size -lt $log_filesize; then
printf "[$process_cmdline]$record"
printf "[$process_cmdline]$record" >> $log_filepath
else
printf "[$process_cmdline]$record" >> $log_filepath
mv $log_filepath $log_filepath.bak # 備份
printf "[$process_cmdline][`date +'%Y-%m-%d %H:%M:%S'`]truncated\n"
printf "[$process_cmdline][`date +'%Y-%m-%d %H:%M:%S'`]truncated\n" > $log_filepath
printf "[$process_cmdline]$record"
printf "[$process_cmdline]$record" >> $log_filepath
fi
fi
}
# 以死迴圈方式,定時檢測指定的進程是否存在
# 一個重要原因是crontab最高頻率為1分鐘,不滿足秒級的監控要求
while true; do
self_count=`ps -C $self_name h -o euser,args| awk 'BEGIN { num=0; } { if (($1==uid || $1==cur_user) && match($0, self_cmdline)) {++num;}} END { printf("%d",num); }' uid=$uid cur_user=$cur_user self_cmdline="$self_cmdline"`
if test ! -z "$self_count"; then
if test $self_count -gt 2; then
log "\033[0;32;31m[`date +'%Y-%m-%d %H:%M:%S'`]$0 is running[$self_count/active:$active], current user is $cur_user.\033[m\n"
# 經測試,正常情況下一般為2,
# 但運行一段時間後,會出現值為3,因此放在crontab中非常必要
# 如果監控指令碼已經運行,則退出不重複運行
if test $active -eq 0; then
exit 1
fi
fi
fi
# 檢查被監控的進程是否存在,如果不存在則重啟
if test -z "$process_match"; then
process_count=`ps -C $process_name h -o euser,args| awk 'BEGIN { num=0; } { if (($1==uid || $1==cur_user)) {++num;}} END { printf("%d",num); }' uid=$uid cur_user=$cur_user`
else
process_count=`ps -C $process_name h -o euser,args| awk 'BEGIN { num=0; } { if (($1==uid || $1==cur_user) && match($0, process_match)) {++num;}} END { printf("%d",num); }' uid=$uid cur_user=$cur_user process_match="$process_match"`
fi
if test ! -z "$process_count"; then
if test $process_count -lt 1; then
# 執行重啟指令碼,要求這個指令碼能夠將指定的進程拉起來
log "\033[0;32;34m[`date +'%Y-%m-%d %H:%M:%S'`]restart \"$process_cmdline\"\033[m\n"
sh -c "$restart_script" >> $log_filepath 2>&1 # 注意一定要以“sh -c”方式執行
fi
fi
active=1
# sleep時間得長一點,原因是啟動可能沒那麼快,以防止啟動多個進程
# 在某些環境遇到sleep無效,正常sleep後“$?”值為0,則異常時變成“141”,
# 這個是因為收到了訊號13,可以使用“trap '' SIGPIPE”忽略SIGPIPE。
sleep $start_seconds
done
exit 0
---------------------------------------------------------指令碼內容--------------------------------------------------------
假設:
1) java安裝目錄為/data/jdk
2) 監控指令碼process_monitor監控指令碼process_monitor.sh安裝目錄為/usr/local/bin
3) hadoop安裝目錄為/data/hadoop
4) hbase安裝目錄為/data/hbase
5) zookeeper安裝目錄為/data/zookeeper
可以通過jps查看到進程ID,然後使用kill命令殺死進程,查看監控重拉起效果。
process_monitor.sh每隔2秒(由變數monitor_interval指定)檢查一次,發現進程不存在時,立即啟動。
假設運行使用者為root,則process_monitor.sh的記錄檔為/tmp/process_monitor-root.log,
假設運行使用者為test,則process_monitor.sh的記錄檔為/tmp/process_monitor-test.log,以此類推。
可以通過tail -f觀察process_monitor.sh的日誌,來瞭解process_monitor.sh的運行。
process_monitor.sh帶兩個參數,
第一個參數是被監控的進程對象,process_monitor.sh依靠第二個參數重啟被監控對象。
第一個參數又分兩部分,第一個空格前的部分,和空格之後的部分。
第一部分為被監控對象的進程名稱,對於java程式,進程名是java,而不是jar包的名稱。
第二部分為參數部分,可有可無,但正是通過它來區分不同的被監控對象,對於java、shell程式等是必須的。
另外,process_monitor.sh對參數部分是採取模糊部分匹配方式。
可以通過ps aux命令來確定進程名稱和參數。
crontab配置如下:
# 監控HDFS NameNode
* * * * * /usr/local/bin/process_monitor.sh "/data/jdk/bin/Java -Dproc_namenode" "/data/Hadoop/sbin/hadoop-daemon.sh start namenode"
# 監控HDFS切換主備NameNode程式
* * * * * /usr/local/bin/process_monitor.sh "/data/jdk/bin/java -Dproc_zkfc" "/data/hadoop/sbin/hadoop-daemon.sh start zkfc"
# 監控HDFS JournalNode
* * * * * /usr/local/bin/process_monitor.sh "/data/jdk/bin/java -Dproc_journalnode" "/data/hadoop/sbin/hadoop-daemon.sh start journalnode"
# 監控HDFS DataNode
* * * * * /usr/local/bin/process_monitor.sh "/data/jdk/bin/java -Dproc_datanode" "/data/hadoop/sbin/hadoop-daemon.sh start datanode"
# 監控Hbase Master
* * * * * /usr/local/bin/process_monitor.sh "/data/jdk/bin/java -Dproc_master" "/data/hbase/bin/hbase-daemon.sh start master"
# 監控HBase thrift2
* * * * * /usr/local/bin/process_monitor.sh "/data/jdk/bin/java -Dproc_thrift2" "/data/hbase/bin/hbase-daemon.sh start thrift2 --framed -nonblocking"
# 監控ZooKeeper
* * * * * /usr/local/bin/process_monitor.sh "/data/jdk/bin/java -Dzookeeper" "/data/zookeeper/bin/zkServer.sh start"
# 監控HBase regionserver
* * * * * /usr/local/bin/process_monitor.sh "/data/jdk/bin/java -Dproc_regionserver" "/data/hbase/bin/hbase-daemon.sh start regionserver"
# 監控YARN ResourceManager
* * * * * /usr/local/bin/process_monitor.sh "/data/jdk/bin/java -Dproc_resourcemanager" "/data/hadoop/sbin/yarn-daemon.sh start resourcemanager"
# 監控YARN NodeManager
* * * * * /usr/local/bin/process_monitor.sh "/data/jdk/bin/java -Dproc_nodemanager" "/data/hadoop/sbin/yarn-daemon.sh start nodemanager"
# 監控HiveServer
* * * * * /usr/local/bin/process_monitor.sh "/data/jdk/bin/Java HiveServer2" "/data/gongyi/Hive/bin/hiveserver2 &"
# 監控Hive MetaStore
* * * * * /usr/local/bin/process_monitor.sh "/data/jdk/bin/java HiveMetaStore" "/data/gongyi/hive/bin/hive --service metastore &"