프로세스가 종료되면 프로세스를 다시 시작하기 위해 bash 스크립트를 작성하는 방법
대기열을 확인하고 각 항목에 대해 작업을 수행하는 Python 스크립트가 있습니다.
# checkqueue.py
while True:
check_queue()
do_something()
bash 스크립트가 실행 중인지 확인하고 그렇지 않은 경우 시작하는 bash 스크립트를 작성하는 방법 대략 다음 의사 코드 (또는 어쩌면 ps | grep
? 와 같은 작업을 수행해야 함 ) :
# keepalivescript.sh
if processidfile exists:
if processid is running:
exit, all ok
run checkqueue.py
write processid to processidfile
나는 crontab에서 그것을 부를 것입니다 :
# crontab
*/5 * * * * /path/to/keepalivescript.sh
PID 파일, 크론 또는 자녀가 아닌 프로세스를 평가하려는 다른 것을 피하십시오.
유닉스에서는 오직 당신의 자녀 만 기다릴 수있는 이유가 있습니다. 이 문제를 해결하려고 시도하는 모든 방법 (ps 구문 분석, pgrep, PID 저장 ...)은 결함이 있으며 그 안에 구멍이 있습니다. 그냥 말할 아니오 .
대신 프로세스를 부모 프로세스로 모니터하는 프로세스가 필요합니다. 이것은 무엇을 의미 하는가? 프로세스를 시작한 프로세스 만 프로세스가 끝날 때까지 안정적으로 기다릴 수 있음을 의미합니다. bash에서 이것은 절대적으로 사소합니다.
until myserver; do
echo "Server 'myserver' crashed with exit code $?. Respawning.." >&2
sleep 1
done
위의 bash 코드는 루프 myserver
에서 실행됩니다 until
. 첫 번째 줄이 시작 myserver
되고 끝날 때까지 기다립니다. 종료되면 until
종료 상태를 확인합니다. 종료 상태가 0
인 경우 정상적으로 종료되었음을 의미합니다 (어쨌든 종료하도록 요청했으며 성공적으로 종료되었음을 의미 함). 이 경우 다시 시작하고 싶지 않습니다 (방금 시스템 종료를 요청했습니다!). 종료 상태 인 경우 하지 0
, until
STDERR에 에러 메시지를 방출 루프 (라인 1 등을) 다시 시작 루프 본문, 실행 1 초 후에을 .
왜 우리는 잠시 기다려? 시작 시퀀스에 문제가 있고 myserver
즉시 충돌하는 경우, 일정하게 다시 시작하고 손에 충돌하는 매우 집중적 인 루프를 갖게됩니다. 은 sleep 1
그에서 긴장을 멀리합니다.
이제이 bash 스크립트 (비동기 적으로)를 시작하기 만하면 myserver
필요에 따라이를 모니터링 하고 다시 시작할 수 있습니다. 부팅시 모니터를 시작하려면 (서버를 "생존"으로 재부팅) @reboot
규칙을 사용하여 사용자의 cron (1)에서 모니터를 예약 할 수 있습니다 . 다음과 crontab
같이 크론 규칙을 엽니 다 .
crontab -e
그런 다음 규칙을 추가하여 모니터 스크립트를 시작하십시오.
@reboot /usr/local/bin/myservermonitor
대안 적으로; inittab (5) 및 / etc / inittab을보십시오. myserver
특정 init 레벨에서 시작하고 자동으로 다시 생성되도록 라인을 추가 할 수 있습니다 .
편집하다.
PID 파일을 사용 하지 않는 이유에 대한 정보를 추가하겠습니다 . 그들은 매우 인기가 있지만; 그들은 또한 매우 결함이 있으며 올바른 방법으로하지 않는 이유가 없습니다.
이걸 고려하세요:
PID 재활용 (잘못된 프로세스 종료) :
/etc/init.d/foo start
: 시작foo
,foo
PID 쓰기/var/run/foo.pid
- 얼마 후 :
foo
어떻게 든 죽는다. - 잠시 후 : 임의의 프로세스가 시작 (호출
bar
)하면 임의foo
의 PID를 사용합니다. 예전 PID를 사용 한다고 상상해보십시오 . - 당신은
foo
사라졌습니다 :/etc/init.d/foo/restart
읽고/var/run/foo.pid
, 아직 살아 있는지 확인하고, 찾고bar
, 생각하고foo
, 죽이고, 새로운 것을 시작합니다foo
.
PID 파일이 오래되었습니다. PID 파일이 오래된 지 여부를 확인하려면 지나치게 복잡하거나 (사소한 말이 아닌) 논리가 필요하며 이러한 논리는 다시 취약합니다
1.
.쓰기 권한이 없거나 읽기 전용 환경에있는 경우 어떻게해야합니까?
무의미한 복잡한 문제입니다. 위의 예제가 얼마나 간단한 지보십시오. 전혀 복잡 할 필요가 없습니다.
참조 : PID 파일이 '올바른'작업을 수행해도 여전히 결함이 있습니까?
그건 그렇고; PID 파일보다 더 나쁜 것은 파싱입니다 ps
! 절대 이러지 마
ps
매우 이식이 불가능합니다. 거의 모든 UNIX 시스템에서 찾을 수 있습니다. 비표준 출력을 원하면 인수가 크게 다릅니다. 그리고 표준 출력은 스크립팅 된 구문 분석이 아닌 사람이 소비 할 수 있습니다!- Parsing
ps
leads to a LOT of false positives. Take theps aux | grep PID
example, and now imagine someone starting a process with a number somewhere as argument that happens to be the same as the PID you stared your daemon with! Imagine two people starting an X session and you grepping for X to kill yours. It's just all kinds of bad.
If you don't want to manage the process yourself; there are some perfectly good systems out there that will act as monitor for your processes. Look into runit, for example.
Have a look at monit (http://mmonit.com/monit/). It handles start, stop and restart of your script and can do health checks plus restarts if necessary.
Or do a simple script:
while true
do
/your/script
sleep 1
done
The easiest way to do it is using flock on file. In Python script you'd do
lf = open('/tmp/script.lock','w')
if(fcntl.flock(lf, fcntl.LOCK_EX|fcntl.LOCK_NB) != 0):
sys.exit('other instance already running')
lf.write('%d\n'%os.getpid())
lf.flush()
In shell you can actually test if it's running:
if [ `flock -xn /tmp/script.lock -c 'echo 1'` ]; then
echo 'it's not running'
restart.
else
echo -n 'it's already running with PID '
cat /tmp/script.lock
fi
But of course you don't have to test, because if it's already running and you restart it, it'll exit with 'other instance already running'
When process dies, all it's file descriptors are closed and all locks are automatically removed.
You should use monit, a standard unix tool that can monitor different things on the system and react accordingly.
From the docs: http://mmonit.com/monit/documentation/monit.html#pid_testing
check process checkqueue.py with pidfile /var/run/checkqueue.pid if changed pid then exec "checkqueue_restart.sh"
You can also configure monit to email you when it does do a restart.
if ! test -f $PIDFILE || ! psgrep `cat $PIDFILE`; then
restart_process
# Write PIDFILE
echo $! >$PIDFILE
fi
I'm not sure how portable it is across operating systems, but you might check if your system contains the 'run-one' command, i.e. "man run-one". Specifically, this set of commands includes 'run-one-constantly', which seems to be exactly what is needed.
From man page:
run-one-constantly COMMAND [ARGS]
Note: obviously this could be called from within your script, but also it removes the need for having a script at all.
I've used the following script with great success on numerous servers:
pid=`jps -v | grep $INSTALLATION | awk '{print $1}'`
echo $INSTALLATION found at PID $pid
while [ -e /proc/$pid ]; do sleep 0.1; done
notes:
- It's looking for a java process, so I can use jps, this is much more consistent across distributions than ps
$INSTALLATION
contains enough of the process path that's it's totally unambiguous- Use sleep while waiting for the process to die, avoid hogging resources :)
This script is actually used to shut down a running instance of tomcat, which I want to shut down (and wait for) at the command line, so launching it as a child process simply isn't an option for me.
'Programing' 카테고리의 다른 글
타임 스탬프를 읽을 수있는 날짜 / 시간 PHP로 변환 (0) | 2020.04.29 |
---|---|
절대 파일 경로를 포함하는 문자열에서 파일 이름을 어떻게 얻습니까? (0) | 2020.04.29 |
재귀 또는 반복? (0) | 2020.04.29 |
기본 FirebaseApp이 초기화되지 않았습니다 (0) | 2020.04.29 |
정기적으로 어떤 Xcode 키보드 단축키를 사용하십니까? (0) | 2020.04.29 |