
나는 그것이 작동하지 않는 것을 제외하고는 그렇게 할 것이라고 생각하는 설정을 생각해 냈습니다.
#!/bin/bash
echo "Launching a background process that may take hours to finish.."
myprog &
pid=$!
retval=
##At this time pid should hold the process id of myprog
echo "pid=${pid}"
{
##check if the process is still running
psl=$(ps -f -p ${pid} | grep -E "\bmyprog\b")
killit=
while [[ ! -z ${psl} ]]
do
##if a file named "kill_flag" is detected, kill the process
if [[ -e "kill_flag" ]]
then
killit=YES
break
fi
#check every 3 seconds
sleep 3
psl=$(ps -f -p ${pid} | grep -E "\bmyprog\b")
done
##killit not set, normal exit, read from fd5
if [[ -z ${killit} ]]
then
read <&5 retval
else
##kill here, the wait will return and the sub process ends
kill ${pid}
fi
} 5< <( wait ${pid} > /dev/null 2>&1; echo $? )
echo "retval=$retval"
처음 실행에서는 모든 것이 괜찮아 보입니다. 로 프로세스를 종료할 수 있습니다 touch kill_flag
. 그렇지 않으면 myprog가 정상적으로 완료될 때까지 기다립니다. 그러나 나는 항상 retval에서 -1을 얻는다는 것을 알았습니다. myprog는 정상적인 실행으로 확인된 대로 0을 반환합니다. 추가 조사에 따르면 " echo $?
" 부분은 wait 명령이 종료된 후가 아니라 스크립트가 시작된 직후에 실행된 것으로 나타났습니다. 여기서 무슨 일이 일어나고 있는지 궁금합니다. 나는 bash를 처음 접했습니다.
답변1
wait
현재 쉘 프로세스의 자식에서만 작동할 수 있습니다. 내부의 코드를 해석하는 서브셸은 <(...)
자매 프로세스를 기다릴 수 없습니다.
대기는 pid를 시작한 동일한 쉘 프로세스에 의해 수행되어야 합니다. zsh
대신에 ( bash
여기서 실행 중인 다른 백그라운드 작업이 없다고 가정):
cmd & pid=$!
while (($#jobstates)) {
[[ -e killfile ]] && kill $pid
sleep 3
}
wait $pid; echo $?
답변2
실행 가능한 버전을 알아냈습니다.
#!/bin/bash
export retval=
##At this time pid should hold the process id of myprog
{
##This is the subshell that launched and monitoring myprog
subsh=$!
##Since myprog is probably the only child process of this subsh, it should be pretty safe
pid=$(ps -f --ppid ${subsh} | grep -E "\bmyprog\b" | gawk '{print $2}' )
##check if the process is still running
psl=$(ps -f -p ${pid} | grep -E "\bmyprog\b")
killit=
while [[ ! -z ${psl} ]]
do
##if a file named "kill_flag" is detected, kill the process
if [[ -e "kill_flag" ]]
then
killit=YES
break
fi
#check every 3 seconds
sleep 3
psl=$(ps -f -p ${pid} | grep -E "\bmyprog\b")
done
##killit not set, normal exit, read from fd5
if [[ -z ${killit} ]]
then
read <&5 retval
else
##kill here, the wait will return and the sub process ends
kill ${pid}
fi
} 5< <( myprog >>logfile 2>&1; echo $? )
echo "retval=$retval"
유일한 짜증나는 점은 세마포어를 사용하여 myprog를 종료할 때 프로세스 대체가 중단되었기 때문에 오류가 발생하지만 쉽게 트랩될 수 있다는 것입니다.