원활한 종료를 위해 ctrl+C를 감지하려면 사용자 정의 명령줄 소프트웨어(예: loopHelloWorld)를 사용하는 것이 좋습니다. 답변을 잃지 않고 어떻게 파이프할 수 있나요 Ctrl+C
?
$ loopHelloWorld
- Ctrl+C to nicely shutdown
그러나 파이프를 사용하면 파이프가 제대로 닫히지 않고 소프트웨어를 종료합니다.
$ loopHelloWorld |
while IFS= read -r line; do
echo "$line"
done
예
ping example.com |
while IFS= read -r line; do
echo "$line"
done
답변1
Ctrl+C파이프의 모든 프로세스에 SIGINT가 전송됩니다(모두 대화형 셸의 포그라운드 작업에 해당하는 동일한 프로세스 그룹에서 실행되기 때문입니다).
그래서:
loopHelloWorld |
while IFS= read -r line; do
echo "$line"
done
실행 중인 프로세스 loopHelloWorld
와 루프의 하위 쉘을 실행하는 프로세스 모두 while
이를 얻습니다 SIGINT
.
메시지가 표준 출력 loopHelloWorld
에 기록 되면 Ctrl+C to nicely shutdown
파이프에도 기록됩니다. 그렇다면뒤쪽에다른 쪽 끝에 있는 서브쉘이 죽었 loopHelloWorld
으면반품SIGPIPE가 수신되었으며 이를 처리해야 합니다.
여기서는 명령의 일반적인 출력이 아니기 때문에 stderr에 메시지를 작성해야 합니다(그러나 이 ping
예에서는 해당되지 않음). 그러면 파이프를 통과하지 못할 것입니다.
또는 while 루프를 실행하는 서브셸이 SIGINT를 무시하여 loopHelloWorld
SIGINT 이후의 출력을 계속 읽도록 할 수 있습니다.
loopHelloWorld | (
trap '' INT
while IFS= read -r line; do
printf '%s\n' "$line"
done
)
그러나 이로 인해 를 누르면 파이프의 종료 상태가 0이 됩니다 Ctrl+C.
이 특정 예에 대한 또 다른 옵션은 대신 zsh
또는 를 사용하는 것입니다 . 이러한 셸에서 루프는 기본 셸 프로세스에서 실행되므로 SIGINT의 영향을 받지 않습니다.ksh93
bash
while
loopHelloWorld | cat
이는 포그라운드 프로세스 그룹에서 실행될 때 cat
도움이 되지 않습니다 .loopHelloWorld
답변2
트랩을 사용하십시오:
#! /bin/bash
trap handleInt SIGINT
interrupted=0
function handleInt {
echo "Interrupted..."
interrupted=1
}
while true
do
[[ interrupted -ne 0 ]] && { echo "Ctrl-C caught, exiting..." ; exit ; }
echo "Sleeping..."
sleep 1
read -r line
echo "$line"
done