파이프 개념을 여러 병렬 파이프라인으로 일반화하는 쉘이 있습니까? 이를 지원하려면 OS 커널을 변경해야 합니까?

파이프 개념을 여러 병렬 파이프라인으로 일반화하는 쉘이 있습니까? 이를 지원하려면 OS 커널을 변경해야 합니까?

명령줄에서 작업할 때 일부 입력 스트림에서 지정한 여러 다른 인스턴스에 대해 동일한 작업을 지정한 다음 해당 출력을 특정 방식으로 재결합하려는 경우가 종종 있습니다.

어제의 두 가지 사용 사례:

  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. 우리는 노트북 서버를 Docker 컨테이너로 분리하는 JupyterHub 인스턴스를 실행합니다. 타임스탬프가 표시된 로그를 보고 싶습니다. 하나의 컨테이너로는 충분히 쉽습니다.

     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하는 것보다 하나의 스트림에서 여러 인증서를 처리하도록 수정하는 것이 훨씬 쉽습니다 .opensslcat

관련 정보