Pipeline como comando paralelo

2

Normalmente, os pipelines no Unix são usados para conectar dois comandos e usar a saída do primeiro comando como a entrada do segundo comando. No entanto, recentemente eu desenvolvi a ideia (que pode não ser nova, mas não encontrei muito Googling) de usar o pipeline para executar vários comandos em paralelo, assim:

command1 | command2

Isso chamará command1 e command2 em paralelo se command2 não ler da entrada padrão e command1 não gravar na saída padrão t. Um exemplo mínimo para ilustrar isso é (por favor, execute-o em um shell interativo)

ls . -R 1>&2|ls . -R

A minha pergunta é, existe alguma desvantagem para usar o pipeline para paralelizar a execução de dois comandos dessa maneira? Há algo que eu tenha perdido nessa ideia?

Muito obrigado antecipadamente.

    
por Weijun Zhou 08.12.2017 / 22:31

2 respostas

6

Os pipelines de comando já são executados em paralelo. Com o comando:

command1 | command2

Ambos command1 e command2 são iniciados. Se command2 estiver programado e o canal estiver vazio, ele ficará bloqueado para leitura. Se command1 tentar gravar no pipe e estiver cheio, command1 bloqueia até que haja espaço para escrever. Caso contrário, command1 e command2 serão executados em paralelo, gravando e lendo do canal.

    
por 08.12.2017 / 22:58
0

Existem desvantagens ...

  1. você não pode ver a saída de command1
  2. se command2 não ler a saída de command1 , o último será interrompido depois de gravar alguma quantidade de saída (vi 4K, mas experimentalmente o limite é de pelo menos 58K para um processo python, veja abaixo ). Isso pode depender do tempo de execução usado por command1 .
  3. se command2 parar antes de command1 e command1 gravar em seu stdout, ele receberá [Errno 32] Broken pipe

Experiência:

cmd1
#! /usr/bin/python3

import sys,time
for i in range(64):
    print ("*"*1023,file=sys.stdout)
    print ("cmd1 here (%d)" % i,file=sys.stderr)
    time.sleep(.1)
print ("cmd1 exiting",file=sys.stderr)
cmd2
#! /usr/bin/python3

import sys,time
for i in range(16):
    print ("cmd2 here (%d)" % i,file=sys.stderr)
    time.sleep(1)
print ("cmd2 exiting",file=sys.stderr)

Executar:

./cmd1 | ./cmd2

Você verá:

  • cmd1 stall na iteração 58 (porque o cmd2 nunca lê nada da sua saída)
  • cmd1 falhando (canal quebrado) quando o cmd2 sai

Então, sim, talvez possa funcionar. E talvez não.

    
por 08.12.2017 / 23:45