단일 파이프라인 항목으로 전체 파이프라인을 볼 수 있나요?

단일 파이프라인 항목으로 전체 파이프라인을 볼 수 있나요?

func표 형식 출력이나 json 출력을 생성할 수 있는 함수가 있습니다 . 이 문제를 해결하는 전통적인 방법은 다음과 같은 매개변수를 사용하는 것입니다.

$ func -j | jq .firstField
$ func -t | awk '{print $1}'

나는 "미리 살펴보고" 파이프라인의 다음 단계를 기반으로 출력 유형을 추론하고 싶습니다. 이상적인 사용법은 간단합니다.

$ func | jq .firstField
$ func | awk '{print $1}'

func 어딘가에서 파이프라인의 다음 단계의 0번째 매개변수가 포함되어 있는지 확인한다고 상상합니다 j. 그렇다면 json을 생성하고, 그렇지 않으면 테이블을 생성합니다.

Bash는 그러한 마법을 허용합니까? 그렇다면 어떻게 해야 할까요?

답변1

/proc프로세스 도구를 통해 프로세스 트리에서 또는 존재하는 경우 유형 파일 시스템을 마이닝하여 회수할 수 있는 것 외에는 파이프라인과 연관된 공식 메타데이터나 쿼리 API가 없습니다 . 상위 셸은 (아마도) 메모리 어딘가에 완전한 파이프를 갖고 있으며 관련된 다양한 하위 프로세스에 대해 알고 있습니다. 하지만 임의 cat의(예를 제외하면 의미 없음) 파이프가 진행 중인 하위 프로세스를 cat | cat | cat | ...알 수 있도록 하는 API는 없습니다 . cat파이프라인과 그 동료가 누구인지 알아보겠습니다.

% cat | cat -b | cat -e | cat -n

고유한 플래그를 사용하면 어떤 것이 pstree(1)다른 터미널에 표시되는지 더 쉽게 알 수 있으므로 더 유용합니다.

 |     \-+= 35276 jhqdoe -zsh (zsh)
 |       |--- 44661 jhqdoe cat -n
 |       |--- 03968 jhqdoe cat -b
 |       |--- 96165 jhqdoe cat -e
 |       \--= 26975 jhqdoe cat

cat -e그러나 이것은 파이프가 무엇인지 알려주지 않고 cat -n, 고양이 가방이 모두 상위 쉘 35276의 프로세스 그룹에 속한다는 것을 알려줍니다.

% ps ao ppid,pid,command | grep '[ ]cat'
35276 44661 cat -n
35276 96165 cat -e
35276  3968 cat -b
35276 26975 cat

어떤 파이프나 설명자가 무엇에 연결되어 있는지 확인하는 pid 또는 명령이 있는 시스템에 있는 경우 /proc프로세스가 속한 프로세스 그룹에서 무엇이 무엇에 연결되어 있는지 알아낼 수 있습니다. 예를 들어 Linux에서 lsof유사한 cat 파이프라인을 실행하면 파이프 14301040을 공유하므로 연결 cat -e하고 명령할 수 있습니다.cat -n

-bash-4.2$ lsof -p 23591 | grep pipe
cat     23591 jhqdoe    0r  FIFO    0,9       0t0 14301039 pipe
cat     23591 jhqdoe    1w  FIFO    0,9       0t0 14301040 pipe
-bash-4.2$ lsof -p 23592 | grep pipe
cat     23592 jhqdoe    0r  FIFO    0,9       0t0 14301040 pipe

따라서 정보를 사용할 수 있더라도 정보를 파악하려면 휴대용이 아닌 도구를 사용하여 많은 정보를 파고 재구성해야 할 수 있습니다.

상위 셸은 입력 후 파이프를 다시 작성하는 방법을 제공할 수 있지만 ZSH 후크 기능은 preexec실행할 명령을 다시 작성하는 방법을 제공하지 않는 것 같습니다. (이러한 기능은 LISP 매크로를 사용하여 프로그래머가 코드를 다시 작성할 수 있게 하는 방법과 유사할 수 있습니다.) 상위 셸은 하위 프로세스가 파이프를 검사하는 데 사용할 수 있는 일종의 API를 제공할 수도 있지만... 이러한 유형의 추가 사항은 셸에 작성해야 합니다. .

그러나 복잡한 파이프라인을 구축할 수 있습니다.

func | ( cd ... && ... | ( ... | awk ... ) )

이 경우 잘못 func찾아 awk반응하지 못하거나 프로세스 파이프라인 검색 기능이 다음 파이프라인 요소에 대한 모든 명령을 재귀적으로 탐색해야 합니다. 이 경우 아마도 즉석 awk에서일 것입니다. func또는 이 동작을 설정했다는 사실을 잊어버리고 awk잘못 수정되어 버그를 찾기 어려울 수도 있습니다...

답변2

적어도 Linux에서는 이 작업을 수행할 수 있었습니다. 이를 보여주는 스크립트는 다음과 같습니다.https://gist.github.com/MatrixManAtYrService/790a4a058bc841b0ceb2eb0263fb5d88

사용 예:

❯ cat -b | ./luigi | jq .
[
  {
    "pid": "20832",
    "name": "cat -b",
    "node": {
      "write": "5157339",
      "read": null
    }
  },
  {
    "pid": "20833",
    "name": "bash ./luigi",
    "node": {
      "write": "5157341",
      "read": "5157339"
    }
  },
  {
    "pid": "20834",
    "name": "jq .",
    "node": {
      "write": null,
      "read": "5157341"
    }
  }
]

관련 정보