¿Hay algún shell que generalice la noción de tuberías a múltiples tuberías paralelas? ¿Para admitirlo se requerirían cambios en el kernel del sistema operativo?

¿Hay algún shell que generalice la noción de tuberías a múltiples tuberías paralelas? ¿Para admitirlo se requerirían cambios en el kernel del sistema operativo?

Muy a menudo, cuando trabajo en la línea de comando, me encuentro especificando la misma operación en un montón de instancias diferentes especificadas por algún flujo de entrada, y luego quiero recombinar sus salidas de alguna manera específica.

Dos casos de uso de ayer:

  1. Quería ver los asuntos de un montón de certificados SSL incluidos en un archivo PEM.

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

    Sólo me muestra el primero. Necesito dividir los certificados y ejecutar el mismo comando en cada uno de ellos, luego concatenar los resultados. csplitPuede dividirlos, pero solo en archivos. Esto es una molestia.

    ¿Por qué no puedo simplemente decir

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

    ?

  2. Ejecutamos una instancia de JupyterHub que divide los servidores portátiles como contenedores Docker. Quiero ver sus registros con marca de tiempo. Es bastante fácil para un contenedor:

     sudo docker logs -t -f $container_id
    

    ( -tAgrega una marca de tiempo y -fmantiene la tubería abierta, como tail -f).

    Es bastante fácil enumerar los registros de todos los contenedores, ordenados por marcas de tiempo:

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

    o

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

    o

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

    pero nada de eso me permitirá usar la -fopción de ver los registros a medida que llegan.

    ¿Por qué no puedo simplemente usar

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

    o

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

    ?

Claramente, esto requiere

  1. Soporte de carcasa específico. Quizás necesitaríamos un símbolo distinto de "multitubo".
  2. Nuevas herramientas ( csplit-tee, on-eachy merge) que dividen y fusionan canalizaciones.
  3. Una convención fija sobre cómo especificar, dentro de las herramientas, muchos descriptores de archivos de entrada y salida de manera arbitraria, de modo que este shell los trate como canalizaciones paralelas.

¿Se ha hecho esto? ¿O algo equivalente que pueda aplicar a mis casos de uso?

¿Es factible sin soporte específico del kernel? Sé que el kernel normalmente tiene un número máximo fijo de descriptores de archivos abiertos, pero una implementación puede solucionarlo al no intentar abrirlos todos a la vez a ciegas.

¿Es factible, sabiendo queparalelo GNU¿Es factible?

Respuesta1

Con GNU Paralelo:

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

No probado:

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

Respuesta2

No, el caparazón no puede hacer eso. Una tubería es simplemente una corriente desde un origen a un destino, generalmente en diferentes procesos.

Veamos su primer ejemplo:

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

Quiere que el archivo de entrada se divida a lo largo de líneas que contengan BEGIN y END, pero catno le importa el contenido y, de todos modos, las canalizaciones no tienen indicación fuera de límite de separadores de registros.

Podría lograr esto con convenciones específicas en el origen y destino de una canalización, pero eliminaría la principal ventaja de una canalización, la de poder combinar programas como bloques de construcción para tareas que no fueron anticipadas por sus autores.

En este ejemplo específico, sería mucho más fácil modificar opensslpara procesar múltiples certificados en una secuencia que modificar opensslpara procesar múltiples secuencias Y modificar catpara proporcionar estas múltiples secuencias.

información relacionada