파이프라인 개념을 여러 병렬 파이프라인으로 일반화하는 셸이 있나요? 이를 지원하려면 운영 체제 커널을 변경해야 합니까?

파이프라인 개념을 여러 병렬 파이프라인으로 일반화하는 셸이 있나요? 이를 지원하려면 운영 체제 커널을 변경해야 합니까?

명령줄을 사용하여 작업할 때 일부 입력 스트림 사양의 다양한 인스턴스에 대해 동일한 작업을 지정한 다음 특정 방식으로 해당 출력을 재결합하고 싶은 경우가 많습니다.

어제의 두 가지 사용 사례:

  1. PEM 파일에 번들로 포함된 SSL 인증서 묶음의 제목을 보고 싶습니다.

     cat mypemfile.crt |
     (openssl x509 -noout -text | fgrep Subject:)
    

    첫 번째 항목만 표시됩니다. 인증서를 분할하고 각 인증서에 대해 동일한 명령을 실행한 다음 결과를 연결해야 합니다. csplit분할할 수 있지만 파일로만 분할할 수 있습니다. 이것은 번거로운 일입니다.

    왜 말을 못하겠어요

     cat mypemfile.crt |
     csplit-tee '/BEGIN/ .. /END/' |
     on-each ( openssl x509 -noout -text | fgrep Subject: ) |
     merge --cat
    

    ?

  2. JupyterHub 인스턴스를 실행하고 노트북 서버를 Docker 컨테이너로 분할합니다. 타임스탬프가 표시된 로그를 보고 싶습니다. 컨테이너의 경우 이는 쉽습니다.

     sudo docker logs -t -f $container_id
    

    ( -t타임스탬프를 추가하고 -f파이프를 열어 두세요 tail -f.)

    타임스탬프별로 정렬하여 모든 컨테이너의 로그를 쉽게 나열할 수 있습니다.

     sudo docker ps | awk '{print $1}' |
     while read container_id
     do
       sudo docker logs -t $container_id
     done |
     sort
    

    또는

     sudo docker ps | awk '{print $1}' |
     xargs -n1 sudo docker logs -t |
     sort
    

    또는

     sudo docker ps | awk '{print $1}' |
     parallel sudo docker logs -t {} |
     sort
    

    -f그러나 이들 중 어느 것도 로그를 보기 위해 해당 옵션을 사용할 수 없습니다 .

    왜 그냥 사용할 수 없나요?

     sudo docker ps | awk '{print $1}' |
     csplit-tee /./ |
     on-each (xargs echo | sudo docker logs -t -f) |
     merge --line-by-line --lexicographically
    

    또는

     sudo docker ps | awk '{print $1}' |
     parallel --multipipe sudo docker logs -t -f {} |
     merge --line-by-line --lexicographically
    

    ?

분명히 이것은 필요합니다

  1. 특정 쉘 지원. 어쩌면 고유한 "다중 파이프라인" 기호가 필요할 수도 있습니다.
  2. 파이프라인 분할 및 병합을 위한 새로운 도구( csplit-tee및 )입니다 on-each.merge
  3. 셸이 병렬 파이프로 처리하도록 도구 내에서 입력 및 출력 파일 설명자를 원하는 수만큼 지정하는 방법에 대한 규칙이 수정되었습니다.

이 작업이 완료되었습니까? 아니면 내 사용 사례에 적용할 수 있는 것과 동등한 것입니까?

특정 커널 지원 없이 이것이 가능합니까? 커널에는 일반적으로 열려 있는 파일 설명자의 최대 개수가 고정되어 있다는 것을 알고 있지만 구현에서는 맹목적으로 모든 파일 설명자를 한 번에 열려고 시도하지 않음으로써 이 문제를 해결할 수 있습니다.

알고보면 가능할까?GNU 병렬가능합니까?

답변1

GNU 병렬 처리 사용:

cat mypemfile.crt |
  parallel --pipe -N1 --recstart '-----BEGIN' 'openssl x509 -noout -text | fgrep Subject:'

테스트되지 않음:

sudo docker ps | awk '{print $1}' |
  sudo parallel -j0 --lb docker logs -t -f {}

sudo docker ps | awk '{print $1}' |
  sudo parallel -j0 --tag --lb docker logs -t -f {}

답변2

아니요, 쉘은 그렇게 할 수 없습니다. 파이프는 일반적으로 다른 프로세스에서 소스에서 대상으로의 단순한 스트림입니다.

첫 번째 예를 살펴보겠습니다.

cat mypemfile.crt |
(openssl x509 -noout -text | fgrep Subject:)

BEGIN 및 END가 포함된 라인을 따라 입력 파일을 분할하기를 원하지만 cat내용은 신경 쓰지 않고 파이프에는 레코드 구분 기호의 범위를 벗어난 표시가 없습니다.

파이프라인 소스와 대상의 특정 규칙을 통해 이를 달성할 수 있지만 이렇게 하면 작성자가 의도하지 않은 작업을 수행하기 위해 프로그램을 빌딩 블록으로 결합하는 기능인 파이프라인의 주요 이점이 제거됩니다.

openssl이 특정 예에서는 openssl여러 스트림을 처리하도록 수정하고 해당 여러 스트림을 제공하도록 수정하는 것보다 하나의 스트림에서 여러 인증서를 처리하도록 수정하는 cat것이 훨씬 쉽습니다 .

관련 정보