Ctrlc백그라운드 프로세스를 실행하고 쉘 스크립트를 사용할 때 하위 프로세스를 종료한 다음 종료되도록 쉘 스크립트를 설정하려고 합니다 .
내가 생각할 수 있는 최선은 이것이다. kill 0 -INT
대기가 발생하기 전에 스크립트도 종료되는 것으로 나타나 므로 쉘 스크립트는 하위 프로세스가 완료되기 전에 종료됩니다.
이 쉘 스크립트가 전송된 후 자식이 죽을 때까지 기다리게 하는 방법에 대한 아이디어가 있습니까 INT
?
#!/bin/bash
trap 'killall' INT
killall() {
echo "**** Shutting down... ****"
kill 0 -INT
wait # Why doesn't this wait??
echo DONE
}
process1 &
process2 &
process3 &
cat # wait forever
답변1
당신의 kill
명령은 거꾸로입니다.
많은 UNIX 명령과 마찬가지로 빼기 기호로 시작하는 옵션은 다른 매개변수 앞에 나타나야 합니다.
당신이 쓴다면
kill -INT 0
-INT
옵션 으로 처리되어 SIGINT
( 현재 프로세스 그룹의 모든 프로세스를 나타내는 특수 번호) 0
로 전송됩니다.0
하지만 쓰다보면
kill 0 -INT
을 보고 0
더 이상 옵션이 없다고 판단하여 SIGTERM
기본값을 사용합니다. 그리고 보내다저것당신이 그랬던 것처럼 현재 프로세스 그룹에
kill -TERM 0 -INT
SIGTERM
(또한 에 보내려고 시도하는데 -INT
이로 인해 구문 오류가 발생하지만 먼저 SIGTERM
에 보내고 0
그 이상 도달하지 않습니다.)
따라서 기본 스크립트 는 SIGTERM
실행 wait
하기 전에 및 echo DONE
.
다음에 추가
trap 'echo got SIGTERM' TERM
맨 위, 바로 뒤에
trap 'killall' INT
그것을 증명하기 위해 다시 실행했습니다.
Stephane Chazelas가 지적했듯이 배경(등)이 있는 자녀는 기본적으로 무시 process1
됩니다 .SIGINT
어쨌든 보내는 것이 SIGTERM
더 합리적이라고 생각합니다.
결국 kill -process group
아이들에게 먼저 준다고 장담할 수는 없을 것 같습니다. 문을 닫을 때는 신호를 무시하는 것이 좋습니다.
그러니 이것을 시도해 보세요:
#!/bin/bash
trap 'killall' INT
killall() {
trap '' INT TERM # ignore INT and TERM while shutting down
echo "**** Shutting down... ****" # added double quotes
kill -TERM 0 # fixed order, send TERM not INT
wait
echo DONE
}
./process1 &
./process2 &
./process3 &
cat # wait forever
답변2
불행히도 백그라운드에서 시작된 명령은 SIGINT를 무시하도록 셸에 의해 설정되며 더 나쁜 것은 작동하지 않는다는 것 trap
입니다.
(trap - INT; exec process1) &
(trap - INT; exec process2) &
trap '' INT
wait
Ctrl-C를 누르면 process1과 process2가 동일한 프로세스 그룹(즉, 터미널의 전경 프로세스 그룹)에 속하기 때문에 SIGINT를 수신하기 때문입니다.
위 코드는 이와 관련하여 POSIX와 호환되지 않는 pdksh 및 zsh와 함께 사용됩니다.
다른 셸의 경우 다음과 같은 다른 방법을 사용하여 SIGINT에 대한 기본 처리기를 복원해야 합니다.
perl -e '$SIG{INT}=DEFAULT; exec "process1"' &
또는 SIGTERM과 같은 다른 신호를 사용하십시오.
답변3
일부 백그라운드 프로세스를 관리하고 싶다면 bash 작업 제어 기능을 사용해 보는 것은 어떨까요?
$ gedit &
[1] 2581
$ emacs &
[2] 2594
$ jobs
[1]- Running gedit &
[2]+ Running emacs &
$ jobs -p
2581
2594
$ kill -2 `jobs -p`
$ jobs
[1]- Interrupt gedit
[2]+ Done emacs
답변4
그래서 그것도 수정했어요. Bash에서는 함수를 정의하고 이를 사용하여 흥미로운 작업을 수행할 수 있습니다. 나와 동료들은 terminator
이를 일괄 실행에 사용합니다. 출력을 보려면 일반적으로 여러 개의 종료자 창을 생성합니다( tmux
탭만큼 우아하지는 않지만 GUI와 유사한 인터페이스를 사용할 수 있습니다. 하하).
제가 생각해낸 설정과 실행할 수 있는 예는 다음과 같습니다.
#!/bin/bash
custom()
{
terun 'something cool' 'yes'
run 'xclock'
terun 'echoes' 'echo Hello; echo Goodbye; read'
func()
{
local i=0
while :
do
echo "Iter $i"
let i+=1
sleep 0.25
done
}
export -f func
terun 'custom func' 'func'
}
# [ Setup ]
run()
{
"$@" &
# Give process some time to start up so windows are sequential
sleep 0.05
}
terun()
{
run terminator -T "$1" -e "$2"
}
finish()
{
procs="$(jobs -p)"
echo "Kill: $procs"
# Ignore process that are already dead
kill $procs 2> /dev/null
}
trap 'finish' 2
custom
echo 'Press <Ctrl+C> to kill...'
wait
실행해
$ ./program_spawner.sh
Press <Ctrl+C> to kill...
^CKill: 9835
9840
9844
9850
$
편집하다 @Maxim 님, 방금 귀하의 제안을 보았는데 훨씬 쉬워졌습니다! 감사해요!