입력 리디렉션 서브쉘에 파이프가 사용되는 경우 Ctrl-c는 쉘을 종료합니다.

입력 리디렉션 서브쉘에 파이프가 사용되는 경우 Ctrl-c는 쉘을 종료합니다.

다음 명령을 실행하면:

cat <(echo 1 | pv) | pv
cat <(echo 1 | pv) | less
cat <(echo 1 | pv) | cat

명령이 영원히 실행되는 것 같습니다. (SIGINT)를 입력하면 ^C실행된 명령뿐만 아니라 전체 쉘이 종료됩니다. 왜 그럴까요?


ps xf다른 쉘의 최소 관련 출력 cat <(pv) | less:

Ss  /bin/bash
S+   \_ cat /dev/fd/XX
S    |   \_ /bin/bash
T    |       \_ pv
S+   \_ less

다음 파일 설명자를 엽니다.

세게 때리다

0 -> /dev/pts/YY
1 -> /dev/pts/YY
2 -> /dev/pts/YY
255 -> /dev/pts/YY

고양이/개발자/fd/ZZ

0 -> /dev/pts/YY
1 -> pipe:[RRRRRRRR]
2 -> /dev/pts/YY
3 -> pipe:[QQQQQQQQ]
ZZ -> pipe:[QQQQQQQQ]

세게 때리다

0 -> /dev/pts/YY
1 -> pipe:[QQQQQQQQ]
2 -> /dev/pts/YY
255 -> /dev/pts/YY

PV

0 -> /dev/pts/YY
1 -> pipe:[QQQQQQQQ]
2 -> /dev/pts/YY

더 적은

0 -> pipe:[RRRRRRRR]
1 -> /dev/pts/YY
2 -> /dev/pts/YY
3 -> /dev/tty

cat <(echo 1 | pv) | less원래 예제를 사용하면( 이것은 bash 내장이 아니라 다른 프로그램인 경우에도 발생합니다. 예:echodd if=/dev/zero bs=1 count=1

Ss   /bin/bash
S+    \_ cat /dev/fd/63
S     |   \_ /bin/bash
T     |       \_ pv
S+    \_ less

세게 때리다

0 -> /dev/pts/18
1 -> /dev/pts/18
2 -> /dev/pts/18
255 -> /dev/pts/18

고양이/개발자/fd/63

0 -> /dev/pts/18
1 -> pipe:[36932796]
2 -> /dev/pts/18
3 -> pipe:[36929317]
63 -> pipe:[36929317]

세게 때리다

0 -> /dev/pts/18
1 -> pipe:[36929317]
2 -> /dev/pts/18
255 -> /dev/pts/18

PV

0 -> pipe:[36930391]
1 -> pipe:[36929317]
2 -> /dev/pts/18

더 적은

0 -> pipe:[36932796]
1 -> /dev/pts/18
2 -> /dev/pts/18
3 -> /dev/tty

답변1

이는 <(프로세스에 )적절한 작업 제어가 없기 때문에 발생합니다. 즉, 포크되고 잊어버리게 됩니다. 대부분의 경우 이것은 중요하지 않습니다. 왜냐하면거의프로세스는 생성되자마자 별도의 프로세스 그룹과 백그라운드에 배치됩니다. ~을 위한즉각적인쉘은 이 프로세스에 대한 입력 및 출력을 열어야 하지만 이는 tty의 전경 프로세스 그룹이므로 SIGINT에 취약합니다. 대화형 쉘이 일반적으로 수행하는 것처럼 포착되거나 무시되지 않는 한입니다.

하지만 문제는 이렇습니다. 파이프라인이 교착 상태에 빠졌습니다. 상위 프로세스가 프로세스의 출력을 열려고 하면 파이프가 차단됩니다. 프로세스 그룹과 다른 모든 그룹을 변경할 기회가 없습니다.CTRL+C전경 그룹이 종료되고 SIGINT가 전송됩니다. 전경 그룹이 종료되고 상위 그룹이 여전히 파이프에 의해 차단되어 제어권을 다시 얻을 수 없는 경우 집에 아무도 없기 때문에 터미널에서 HUP를 보냅니다.카붐

다른 파이프를 열려면 먼저 여는 각 파이프에 대해 작성자와 판독기가 필요합니다.

관련 정보