이 작업을 수행할 것이라고 생각한 설정을 생각해 냈지만 작동하지 않습니다.
#!/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를 종료할 때 프로세스 교체가 중단되어 오류가 나타나는데 쉽게 잡힐 수 있다는 것입니다.