Algum shell generaliza a noção de tubos para vários pipelines paralelos? Apoiá-lo exigiria alterações no kernel do sistema operacional?

Algum shell generaliza a noção de tubos para vários pipelines paralelos? Apoiá-lo exigiria alterações no kernel do sistema operacional?

Muitas vezes, ao trabalhar na linha de comando, encontro-me especificando a mesma operação em várias instâncias diferentes especificadas por algum fluxo de entrada e, em seguida, querendo recombinar suas saídas de alguma maneira específica.

Dois casos de uso de ontem:

  1. Eu queria ver os assuntos de vários certificados SSL agrupados em um arquivo PEM.

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

    só me mostra o primeiro. Preciso dividir os certificados e executar o mesmo comando em cada um deles e concatenar os resultados. csplitpode dividi-los, mas apenas em arquivos. Isso é um incômodo.

    Por que não posso simplesmente dizer

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

    ?

  2. Executamos uma instância JupyterHub que divide servidores de notebook como contêineres Docker. Quero observar seus registros com carimbo de data e hora. É bastante fácil para um contêiner:

     sudo docker logs -t -f $container_id
    

    (O -tadiciona um carimbo de data/hora e -fmantém o canal aberto, como tail -f.)

    É fácil listar os logs de todos os contêineres, classificados por carimbos de data/hora:

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

    ou

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

    ou

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

    mas nada disso me permitirá usar a -fopção de observar os logs conforme eles chegam.

    Por que não posso simplesmente usar

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

    ou

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

    ?

Claramente, isso requer

  1. Suporte específico para shell. Talvez precisássemos de um símbolo distinto de "multi-pipe".
  2. Novas ferramentas ( csplit-tee, on-eache merge) que dividem e mesclam pipelines.
  3. Uma convenção fixa sobre como especificar, dentro das ferramentas, arbitrariamente muitos descritores de arquivos de entrada e saída, de modo que esse shell os trate como pipelines paralelos.

Isso foi feito? Ou algo equivalente que eu possa aplicar aos meus casos de uso?

É viável sem suporte específico ao kernel? Eu sei que o kernel normalmente tem um número máximo fixo de descritores de arquivos abertos, mas uma implementação pode contornar isso, não tentando cegamente abri-los todos de uma vez.

É viável, sabendo queParalelo GNUÉ viável?

Responder1

Com GNU Paralelo:

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

Não testado:

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 {}

Responder2

Não, o shell não pode fazer isso. Um pipe é apenas um fluxo de uma origem para um destino, geralmente em processos diferentes.

Vejamos seu primeiro exemplo:

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

Você deseja que o arquivo de entrada seja dividido ao longo de linhas contendo BEGIN e END, mas catnão se importa com o conteúdo, e os pipes não possuem indicação fora do limite de separadores de registros.

Você poderia conseguir isso com convenções específicas na origem e no destino de um pipe, mas isso eliminaria a principal vantagem de um pipe, ser capaz de combinar programas como blocos de construção para tarefas que não foram previstas por seus autores.

Neste exemplo específico, seria muito mais fácil modificar opensslpara processar vários certificados em um fluxo do que modificar opensslpara processar vários fluxos E modificar catpara fornecer esses vários fluxos.

informação relacionada