bash 함수를 사용하여 자체에 대한 일부 정보를 stderr에 덤프한 다음 이를 호출하여 cat
파이프라인을 형성하는 경우, 파이프라인의 어느 단계가 다른 단계를 호출하는지 어떻게 알 수 있습니까?
한 가지 해결책은 각 단계에 , , , , 와 같은 이름을 지정하는 것입니다. a
그러면 출력을 보면 알 수 있습니다. 하지만 단계 이름을 지정하고 싶지 않다고 가정해 보겠습니다. 스테이지의 파일 디스크립터를 보고 한 스테이지가 다른 스테이지의 파일 디스크립터인지 확인하여 전자가 후자로 파이프되고 있음을 알 수 있는 방법이 있습니까? 그렇다면 공유 파이프를 어떻게 식별합니까? 시도했지만 체인을 만드는 방법을 모르겠습니다.b
c
d
a > b > c > d
stdout
stdin
lsof
예를 들어,
printf '%s\n' main "$(lsof -p $$ | grep dev)" > /dev/stderr
pipe() {
printf '%s %s:%s %s\n' $1 $BASHPID $BASH_SUBSHELL $$ > /dev/stderr
printf '%s\n' $1 "$(lsof -p $$ | grep dev)" > /dev/stderr
cat
}
echo
echo hi | pipe a | pipe b | pipe c | pipe d
생산
main
bash 51147 Setup 0u CHR 16,2 0t476770 3717 /dev/ttys002
bash 51147 Setup 1u CHR 16,2 0t476770 3717 /dev/ttys002
bash 51147 Setup 2u CHR 16,2 0t476770 3717 /dev/ttys002
bash 51147 Setup 26u CHR 15,0 0t214349 579 /dev/ptmx
bash 51147 Setup 27u CHR 15,1 0t1206500 579 /dev/ptmx
a 51176:1 51147
d 51147:0 51147
b 51177:1 51147
c 51179:1 51147
b
bash 51147 Setup 1u CHR 16,2 0t477304 3717 /dev/ttys002
bash 51147 Setup 2u CHR 16,2 0t477304 3717 /dev/ttys002
bash 51147 Setup 26u CHR 15,0 0t214349 579 /dev/ptmx
bash 51147 Setup 27u CHR 15,1 0t1206500 579 /dev/ptmx
bash 51147 Setup 254u CHR 16,2 0t477304 3717 /dev/ttys002
d
bash 51147 Setup 1u CHR 16,2 0t477304 3717 /dev/ttys002
bash 51147 Setup 2u CHR 16,2 0t477304 3717 /dev/ttys002
bash 51147 Setup 26u CHR 15,0 0t214349 579 /dev/ptmx
bash 51147 Setup 27u CHR 15,1 0t1206500 579 /dev/ptmx
bash 51147 Setup 254u CHR 16,2 0t477304 3717 /dev/ttys002
a
bash 51147 Setup 1u CHR 16,2 0t477304 3717 /dev/ttys002
bash 51147 Setup 2u CHR 16,2 0t477304 3717 /dev/ttys002
bash 51147 Setup 26u CHR 15,0 0t214349 579 /dev/ptmx
bash 51147 Setup 27u CHR 15,1 0t1206500 579 /dev/ptmx
bash 51147 Setup 254u CHR 16,2 0t477304 3717 /dev/ttys002
c
bash 51147 Setup 1u CHR 16,2 0t478702 3717 /dev/ttys002
bash 51147 Setup 2u CHR 16,2 0t478702 3717 /dev/ttys002
bash 51147 Setup 26u CHR 15,0 0t214349 579 /dev/ptmx
bash 51147 Setup 27u CHR 15,1 0t1206500 579 /dev/ptmx
bash 51147 Setup 254u CHR 16,2 0t478702 3717 /dev/ttys002
hi
stdout
하지만 for에 식별자가 표시되지 않습니다 .a
stdin
b
답변1
파이프는 명명된 파이프와 달리 익명입니다.pipe(2)
주문하다. 그러나 분명히 내부 ID가 표시되어 있습니다 lsof
(에서 확인할 수 있음 ls -l /proc/<pid>/fd
).
하지만 stdout의 식별자가
a
stdin이라는 것을 알 수 없습니다b
.
이는 lsof
올바른 프로세스를 사용하지 않기 때문입니다. $$
파이프 명령으로 생성된 서브셸의 PID가 아닌 스크립트 PID로 확장됩니다. $BASHPID
대신 사용해야 합니다 .
다음과 같이 함수를 수정하세요.
pipe() {
local pid=$BASHPID
printf '%s %s:%s %s\n' "$1" "$pid" "$BASH_SUBSHELL" $$ > /dev/stderr
printf '%s\n' "$1" "$(lsof -a -p "$pid" -d 0,1)" > /dev/stderr
cat
}
이제 다음과 같은 결과를 얻게 됩니다:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
bash 1290 xhienne 0r FIFO 0,12 0t0 180254229 pipe
bash 1290 xhienne 1w FIFO 0,12 0t0 180254230 pipe
...여기서 노드 번호는 파이프의 내부 ID입니다. 그러면 파이프 #12345678이 stdout을 a
stdin b
등에 연결하는 것을 볼 수 있습니다 .