私はZabbix監視サービスの実行が停止したときに自動的に再起動するために使用できるスクリプトを開発してきました。私のスクリプトはうまくいきますが、改善できると思います。
#!/bin/bash
zabbix_server="service zabbix-server"
zabbix_agent="service zabbix-agent"
logfile=zabbix_auto_restart.log
logfilePath=/etc/scripts/zabbix/$logfile
zabbix_server_running=0
zabbix_agent_running=0
grep_agent (){
local retval=$(ps -ef | grep -v grep | grep zabbix_agentd | wc -l)
echo $retval
}
grep_server (){
local retval=$(ps -ef | grep -v grep | grep zabbix_server | wc -l)
echo $retval
}
check_zabbix_agentd (){
if (( $(grep_agent) == 0 ))
then
$zabbix_agent start
echo `date` "$zabbix_agent was stopped... Restarting" >> $logfile
echo "************************************************" >> $logfile
#Send email to notify that the script ran
echo "$(date) $zabbix_agent was restarted from zabbix_restart.sh" | mutt -s "Zabbix Auto-restart Script Just Ran" <user email>
else
let zabbix_agent_running=1
fi
}
check_zabbix_server (){
if (( $(grep_server) == 0 ))
then
$zabbix_server start
echo `date` "$zabbix_server was stopped... Restarting" >> $logfile
echo "************************************************" >> $logfile
#Send email to notify that the script ran
echo "$(date) $zabbix_server was restarted from zabbix_restart.sh" | mutt -s "Zabbix Auto-restart Script Just Ran" <user email>
else
let zabbix_server_running=1
fi
}
main_loop (){
until ((zabbix_server_running == 1 && zabbix_agent_running == 1));
do
check_zabbix_agentd
check_zabbix_server
sleep 1.5
done
}
main_loop
答え1
実際に間違っているのは、努力を複製することです。デフォルトでは、_agent
ハードコードされたすべての項目が発生したり、_server
完全に重複しているように見えます。
たとえば、Linuxシステムで実行している場合は、これらのgrep_...()
機能を完全に削除し、両方のcheck_...
機能を1つのエンティティにマージできます。これは次のように機能します。
email(){
mutt -s "Zabbix Auto-restart Script Just Ran" \<user email\>
}
prlog(){
date +"%x %X:%tservice $1${2+%n************************}"
}
chk_run()
while [ "$#" -gt 0 ]
do if ps -C zabbix_"$1"
then : "$(($1=1))"
else set zabbix_"$@"
service "$1" start || eval >&2 '
prlog "$1 restart failed." +; exit '"$?"
prlog "$1 restarted." + >&2
prlog "$1 restarted from $0." |email
fi; shift
done
重要なことは、chk_run
パラメータリストを使用して呼び出しを実行することです。各メンバーは、各反復について確認する必要があることを示します。
loop()
until [ "$(($1&&$2))" -eq 1 ]
do chk_run "$@"
sleep 2
done >/dev/null 2>>"$log"
agentd=0 server=0 loop agentd server
POSIXで変更する唯一のことはps
コマンドです。 POSIX は-C
スイッチを指定しないためです。したがって、if
この行を次のように変更できます。
if ps -eocomm= |
grep -xqF zabbix_"$1"
最適化をmutt
除いて、標準のコマンド言語でなければなりません。service
ps
標準構文の少なくとも1つの利点は、#!/bin/bash
ハッシュバンが完全に不要であることです。これには、一部のシェル固有の拡張用のアンカーがないため、POSIX 準拠を目指すすべてのシェルでほぼ同じでなければなりません。つまり、#!/bin/dash
とても簡単です。(そしてうまくいくかもしれません)この場合は最適化してください。
もちろん、最適化されているかどうかにかかわらず、このスクリプトはほとんど常にsleep
。
私は定義することを拒否します$log
。主にあなたがそれを定義する方法について話すことがないからです。そしてそれは大丈夫です。考えるもう定義しないでください。スクリプトの呼び出し環境を決定できる場合は、引数を渡す非常に簡単な方法になります。つまり、スクリプトが呼び出され、./script
すでに実行可能である場合...
log=/dev/tty ./script
...呼び出し時に環境に値を設定します$log
。./script
/dev/tty
出力ファイルを例として使用する理由は、十分に調整しながら起動する必要があると思うからです。ここにコードブロックを入れて./script
上記のように実行すると、一部の出力ファイルではなくリアルタイムで端末に書き込まれるため、実際のログファイルにどのような内容が表示されるのかを明確に知ることができます。最後に、次のように呼び出します。
log=./real/logfile ./script
あるいは、ハイブリッドの動作ではなく、次のように表示されるようにスクリプトを変更することもできます2>>"$log"
。
2>>"${log:-/hardcoded/default/path/to/logfile}"
...この場合、シェルは$log
まだ定義されていないハードコードされた値を使用します。これは次のことを意味します。
export log=/dev/tty; ./script
log=/dev/tty ./script
...引き続き端末にログファイルを記録します...
log= ./script
unset log; ./script
...ハードコードされたパスに書き込む...
./script
$log
...現在のシェル環境にエクスポートするために、NULL以外の値がすでに存在するかどうかに応じて、ハードコードされたパスまたは別の場所に書き込まれます。