저는 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_...
기능을 하나의 엔터티로 병합할 수 있습니다. 이는 다음과 같이 작동할 수 있습니다.
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
표준 구문의 최소한 한 가지 장점은 #!/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
...현재 쉘 환경으로 내보내기 위해 널이 아닌 값이 이미 존재하는지 여부에 따라 하드코드된 경로나 다른 위치에 기록됩니다.