Eu tenho dois programas de linha de comando que normalmente são executados em série em um sistema linux.
Execução típica para ambos os programas é simplesmente isso:
- O programa A é executado. É inserir um arquivo de texto simples e gera um arquivo de texto simples.
- O programa B é executado após A, sua entrada é o arquivo de texto que o programa A produziu. Também gera um arquivo de texto simples.
Nota: para ambos os programas acima, suas entradas e saídas são simplesmente caminhos para os respectivos arquivos de entrada e saída. Exemplo:
$ prog_a /path/to/inputfile/dataIn.txt /path/to/outputfile/dataOut.txt
$ prog_b /path/to/inputfile/dataOut.txt /path/to/outputfile/results.txt
Estes são programas desenvolvidos por terceiros. Assim, não podemos modificá-los facilmente (pelo menos não de maneira oportuna). No entanto, queremos acelerar a execução, executando-os em paralelo usando pipes nomeados. Os arquivos de dados são extremamente grandes, por vezes, e processamento paralelo, assumimos que iria acelerar as coisas. Eu fui encarregado deste projeto e procedi da seguinte forma.
Escreveu um script bash onde:
- Crie um pipe nomeado que vincule os dois programas. Chame isso de dataOut.pipe
- O programa A lê o arquivo de texto como de costume, mas em vez de gravar em um arquivo de texto como antes, ele grava no pipe criado na etapa 1, dataOut.pipe
- O programa B lê o canal que foi gerado pelo programa A.
O script bash parece com algo assim:
\#!/bin/bash
mkfifo dataOut.pipe
prog_b dataOut.pipe results.txt &
prog_a dataIn.txt dataOut.pipe
rm dataOut.pipe
Agora isso funciona ... às vezes ... Muitas vezes eu recebo um spitout de exceção java para stderror. E não consigo descobrir qual é exatamente o problema, mas acho que é algo ao longo da linha:
Poderia o programa B, às vezes, rodar mais rápido que A e limpar o tubo mais rápido do que A pode colocar dados nele, o que faz com que a coisa toda caia?
Se for esse o caso, o que é um trabalho fácil? Ou poderia haver algo mais acontecendo?