많은 외부 프로세스를 호출하는 대규모 스크립트에 대해 시간 초과를 구현하려고 합니다.
시간 초과에 도달했는지 매초 확인하는 감시자로 별도의 프로세스를 시작합니다.
(
PARENT_PID=$$
((t = 2 ))
while ((t > 0)); do
sleep 1
((t -= 1))
done
kill -s ALRM ${PARENT_PID} 2> /dev/null
) &
그런 다음 ALRM
메인 스크립트에서 신호를 포착합니다.
trap critical ALRM
마지막으로 키 기능에서 일부 텍스트를 인쇄하고 프로그램을 깔끔하게 종료합니다.
이제 문제가 발생합니다
- $PARENT_PID가 실행되는 동안 시간 초과가 발생하면 모든 것이 예상대로 작동합니다.
- 하위 프로세스가 실행되는 동안 시간 초과가 발생하면(예: openssl을 호출하고 openssl이 실행 중인 경우) 아무 일도 일어나지 않습니다. 실행 중인 하위 프로세스를 종료하면(예: CRTL+ 키를 눌러 C) 상위 프로세스 트랩이 활성화되고 모든 것이 예상대로 계속됩니다.
이 문제를 어떻게 해결할 수 있나요? 그러면 상위 프로세스의 트랩이 호출되고 전체 프로세스를 종료할 수 있습니까?
고쳐 쓰다
감시자가 -KILL
상위 프로세스를 종료하면 모든 하위 프로세스를 처리하는 프로세스가 예상대로 종료됩니다.
문제는 시간 초과를 가로채서 일부 출력을 생성하고 싶다는 것입니다. 이를 위해 ALRM 신호를 사용합니다.
신호는 KILL
무시할 수 없으며 신호도 무시할 수 있습니다 ALRM
.
현재 나의 생각은 다음과 같습니다.
- 상위 프로세스에는 경고 트랩이 있습니다.
- 하위 프로세스가 경고 신호를 무시합니다.
- 신호가 상위 프로세스로 전송되면 하위 프로세스가 실행 중이고 상위 프로세스는 백그라운드에 있습니다.
- 자식이 종료되면 내 프로세스가 깨어납니다.
이것이 맞다면 내 생각은 결코 작동하지 않을 것입니다.
그것이 작동하도록 하려면 각 하위 프로세스마다 있어야 합니다.
- 백그라운드에서 시작하세요
- 기다려 계속
이렇게 하면 상위 프로세스가 신호를 포착할 수 있습니다.
내가 맞나요?
업데이트 2
단순화된 예
critical() {
printf "whathever\n"
WATCHDOG_PID=$!
kill -TERM $WATCHDOG_PID
}
(
PARENT_PID=$$
((t = "${TIMEOUT}" ))
while ((t > 0)); do
sleep 1
((t -= 1))
done
kill -s ALRM ${PARENT_PID} 2> /dev/null
) &
trap critical ALRM
# an example of a long running command
(echo 'Q' | openssl s_client -connect corti.li:imap -servername corti.li -verify 6 ) &
wait
WATCHDOG_PID=$!
kill -TERM $WATCHDOG_PID
openssl
ALRM 신호가 런타임에 전송되면 아무 일도 일어나지 않습니다. openssl
백그라운드에서도 트랩이 호출되지 않습니다 .
답변1
전체 답변을 얻으려면 부모의 코드가 필요하지만, 코드가 부족한 경우 발생할 수 있는 힌트는 다음과 같습니다.
오픈그룹 기본사양 6호 -섹션 2.11
유틸리티가 포그라운드 명령 실행이 완료되기를 기다리는 동안 쉘이 트랩이 설정되었다는 신호를 수신하면,이 신호와 관련된 트랩은 전경 명령이 완료될 때까지 실행되지 않습니다.
쉘이
wait
유틸리티를 통해 비동기 명령이 완료되기를 기다리는 동안 트랩 설정 신호를 수신하면 유틸리티가wait
종료 상태 >128로 즉시 반환되고 그 직후 관련 트랩이 신호를 받아야 합니다.
(내 포맷)
wait
이는 상위 프로세스가 명령 이외의 다른 것을 기다리고 있는 경우 수행 중인 작업이 완료될 때까지 신호 처리가 지연됨을 의미합니다 .
wait
SIGALRM을 즉시 받을 수 있도록 부모님께 기다려 달라고 요청할 수 있습니다 .