다음과 같은 스크립트가 있다고 가정해 보겠습니다.
#!/usr/bin/env zsh
./subscript.sh &
# do stuff
...
# do more stuff
다음과 같은 경우 실행 중인 프로세스 subscript.sh
(및 이에 의해 시작된 모든 프로세스)가 완전히 종료되기를 원합니다.
- 위 스크립트가 종료됩니다.
- 위 스크립트는 어떤 이유로든 종료됩니다.
위 사항을 어떻게 시행하나요? 이것이 쉘에 의해 자동으로 처리됩니까?
답변1
쉘은 결코 자식 프로세스를 자발적으로 종료하지 않습니다. 결국, 백그라운드 작업은 백그라운드에서 실행되어야 하며 부모 프로세스의 수명에는 신경 쓰지 않습니다. (어떤 경우에는 대화형 쉘이 종료 시 하위 프로세스를 종료합니다. 이는 항상 바람직한 것은 아니므로nohup
.)
쉘 스크립트가 트랩 가능한 신호에 의해 종료되거나 종료될 때 백그라운드 작업을 종료하도록 할 수 있습니다. 작업의 프로세스 ID를 기록하고 트랩에서 종료합니다. 이는 하위 작업이 아닌 작업만 종료합니다(원래 프로세스가 백그라운드에서 시작되었으므로).
jobs=()
trap '((#jobs == 0)) || kill $jobs' EXIT HUP TERM INT
…
subscript1 & jobs+=($!)
subscript2 & jobs+=($!)
…
모든 프로세스와 해당 하위 프로세스가 종료되도록 하려면 추가 계획이 필요합니다. 한 가지 접근 방식은 모든 프로세스가 고유한 파일을 열도록 배열하는 것입니다. 모든 프로세스를 종료하려면 파일이 열려 있는 모든 프로세스를 종료하세요. 하위 프로세스는 파일을 닫아 탈출할 수 있습니다.
#!/bin/sh
lock_file=$(mktemp)
exec 3<"$lock_file"
your_script
status=$?
exec 3<&-
fuser -k "$lock_file"
exit $status
답변2
EXIT를 캡처하고 스크립트의 프로세스 그룹에 신호를 보낼 수 있습니다.
리눅스에서
trap 'kill -SIGTERM 0' EXIT
FreeBSD에서
trap 'kill -15 -$$' EXIT
SIGKILL
스크립트가 무조건 종료되기 때문에 작동하지 않는 유일한 신호입니다.