한 명령이 다른 명령으로 파이프되는지 확인하는 방법은 무엇입니까?

한 명령이 다른 명령으로 파이프되는지 확인하는 방법은 무엇입니까?

bash 함수를 사용하여 자체에 대한 일부 정보를 stderr에 덤프한 다음 이를 호출하여 cat파이프라인을 형성하는 경우, 파이프라인의 어느 단계가 다른 단계를 호출하는지 어떻게 알 수 있습니까?

한 가지 해결책은 각 단계에 , , , , 와 같은 이름을 지정하는 것입니다. a그러면 출력을 보면 알 수 있습니다. 하지만 단계 이름을 지정하고 싶지 않다고 가정해 보겠습니다. 스테이지의 파일 디스크립터를 보고 한 스테이지가 다른 스테이지의 파일 디스크립터인지 확인하여 전자가 후자로 파이프되고 있음을 알 수 있는 방법이 있습니까? 그렇다면 공유 파이프를 어떻게 식별합니까? 시도했지만 체인을 만드는 방법을 모르겠습니다.bcda > b > c > dstdoutstdinlsof

예를 들어,

    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에 식별자가 표시되지 않습니다 .astdinb

답변1

파이프는 명명된 파이프와 달리 익명입니다.pipe(2)주문하다. 그러나 분명히 내부 ID가 표시되어 있습니다 lsof(에서 확인할 수 있음 ls -l /proc/<pid>/fd).

하지만 stdout의 식별자가 astdin이라는 것을 알 수 없습니다 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을 astdin b등에 연결하는 것을 볼 수 있습니다 .

관련 정보