셸 파이프에서 프로세스 신호 "종료" 메시지 출력을 캡처합니다.

셸 파이프에서 프로세스 신호 "종료" 메시지 출력을 캡처합니다.

프로세스가 신호를 통해 종료되면 사용된 신호 와 유사 Terminated하거나 이에 따라 달라지는 메시지가 출력됩니다. Killed이 메시지를 캡처할 수 있나요?

다음 파이프라인을 예로 들어 보겠습니다.

while true; do timeout 2 sleep 5; done

아무것도 출력하지 않고 sleep2초마다 종료됩니다. 하나를 추가하세요 cat:

while true; do timeout 2 sleep 5 | cat; done

이제 Terminated2초마다 출력되지만 cat볼 수 없습니다. 로 바꾸면 cat파일 tee somefile이 여전히 비어 있습니다.

2>&1명령줄의 다양한 위치에서 리디렉션을 시도했지만 출력을 Terminated파일로 가져올 수 없습니다.

libc루프가 아닌 터미널 쉘에 연결된 명령을 통해 출력되는 것 같습니다 .

Terminated유사한 출력을 파이프에 넣을 수 있습니까 ?

sleep(궁극적으로 the를 a로, curlthe를 스크립트로 바꾸고 출력과 메시지를 처리하고 싶습니다 .)catawkcurlTerminated

답변1

분석하다

예, 이것이 쉘이 인쇄하는 것입니다 Terminated. 해고되었기 때문에 timeout 2 sleep 5 | cat볼 때 . 그리고 나Terminatedcat하다의미는 입니다 cat.

이에 대한 설명은 다음과 같습니다.내 다른 답변은 다음과 같습니다.. timeout귀하의 경우에는 SIGTERM을 전체 프로세스 그룹에 보내십시오.sleep 그리고 cat.

프로세스 그룹 timeout도 포함됩니다. 자체 신호에 의해 종료되지 않는 것 같습니다. 이것이 timeout단독이 셸을 인쇄하지 않는 이유입니다. 그러나 이렇게 하면 SIGKILL을 포착하거나 무시할 수 없기 때문에 쉘에서 이를 볼 수 있습니다. SIGKILL로 죽이면 스스로 죽고 쉘이 반응합니다.timeout 2 sleep 5Terminatedtimeout -s KILL 2 sleep 5Killedtimeoutsleep

그래서 그것이 당신이 관찰하는 것이 cat가장 중요 합니다 Terminated. 이제 , sleep으로 바꾸면 합계 curl가 종료 됩니다 . 그러나 메시지를 인쇄하는 것은 셸이기 때문에 중요하지 않습니다. 정말로 메시지를 캡처하려면 파이프에서 캡처해야 합니다.catawktimeoutcurlawkawk뒤쪽에껍데기.


해결책

정말로 메시지를 캡처하려면 awk메시지를 인쇄하는 셸 뒤에 파이프를 추가해야 합니다. 그리고 종료된 "피해자" 프로세스가 필요하며, 이 프로세스가 없으면 메시지가 없습니다. 그리고 PID와 동일한 PGID를 가진 프로세스 그룹에서 실행되는 쉘이 필요합니다 timeout. 이는 메커니즘에 중요하기 때문입니다(링크된 답변 참조). 예를 들어 awk다음 파이프라인에서는 메시지가 성공적으로 처리되어야 합니다.

bash -ic 'timeout 2 sleep 5 | cat' 2>&1 | awk '{print "This is the message: "$0}'

-i그것은 중요합니다. 그것 없이는 timeout우리의 불쌍한 비난자들을 죽이지 않을 것입니다 cat. 엄밀히 말하면 이는 대화형 또는 비대화형 Bash와는 아무런 관련이 없습니다. 여기에는 작업 제어 활성화(대화형 Bash에서 기본적으로 활성화됨) 또는 비활성화(비대화형 Bash에서 기본적으로 활성화됨)가 포함됩니다. 따라서 이것은 또한 작동합니다:

bash -c 'set -m; timeout 2 sleep 5 | cat' 2>&1 | awk '{print "This is the message: "$0}'

더욱 우아한 솔루션

원하는 것을 수행하는 더 쉬운 방법이 있습니다. 결국 스크립트에서 실행하려는 경우 스크립트를 해석하는 셸이 해당 명령에 대해 별도의 프로세스 그룹을 생성해서는 안 된다는 사실을 활용할 수 있습니다. 비대화형 스크립트에서는 timeout … | awk종료되지 않습니다 awk.

이제 당신에게 필요한 것은 timeout -v그것이 무엇을 하는지 듣는 것뿐입니다. 다음 예제는 비대화형 스크립트로 실행되도록 설계되었습니다. 대화형 Bash에서 테스트하려면 가능하지만 먼저 작업 제어( set +m)를 비활성화해야 합니다. 스크립트는 다음과 같습니다.

#/bin/sh
timeout -v 2 sleep 5 2>&1 | awk '{print "This is the message: "$0}'

sleep사용. . . 교체 curl. 탐지하려고 하기보다는 awk찾아보아야 합니다 .timeout: sending signal TERM to command '…'Terminated

관련 정보