Multi-Threading / Forking em um script bash

9

Eu escrevi um script bash que está no seguinte formato:

#!/bin/bash
start=$(date +%s)
inFile="input.txt"
outFile="output.csv"

rm -f $inFile $outFile

while read line
do

    -- Block of Commands

done < "$inFile"

end=$(date +%s)

runtime=$((end-start))

echo "Program has finished execution in $runtime seconds."

O whileloop lerá $inFile, executará alguma atividade na linha e fará o dump do resultado $outFile.

Como as $inFile3500+ linhas de comprimento, o script levaria de 6 a 7 horas para ser executado completamente. Para minimizar esse tempo, estou planejando usar multithreading ou bifurcação neste script. Se eu criar 8 processos filhos, 8 linhas $inFileserão processadas simultaneamente.

Como isso pode ser feito?

Mandar Shinde
fonte
Cuidado: scripts diferentes precisarão gravar em arquivos diferentes . Além disso, seu script como escrito exclui o arquivo de entrada como a primeira ação!
Pjc50

Respostas:

10

O GNUparallel é feito para esse tipo de coisa. Você pode executar seu script várias vezes ao mesmo tempo, com dados diferentes da entrada inseridos para cada um:

cat input.txt | parallel --pipe your-script.sh

Por padrão, ele gerará processos de acordo com o número de processadores em seu sistema, mas você pode personalizá-lo com -j N.

Um truque particularmente interessante é o recurso de quebra de linha. Se você alterar a primeira linha do seu script Bash para:

#!/usr/bin/parallel --shebang-wrap --pipe /bin/bash

e alimente os dados com a entrada padrão, tudo acontecerá automaticamente. Isso é menos útil quando você tem um código de limpeza que precisa ser executado no final, o que você pode fazer.

Há algumas coisas a serem observadas. Uma é que ele divide sua entrada em partes seqüenciais e as usa uma de cada vez - não entrelaça linhas. A outra é que esses pedaços são divididos por tamanho, sem levar em consideração quantos registros existem. Você pode usar --block Npara definir um tamanho de bloco diferente em bytes. No seu caso, não mais que um oitavo do tamanho do arquivo deve estar quase certo. Parece que seu arquivo pode ser pequeno o suficiente para terminar em um único bloco, o que anularia o objetivo.

Existem muitas opções para casos de uso diferentes, mas o tutorial aborda as coisas muito bem. Opções nas quais você também pode estar interessado em incluir --round-robine --group.

Michael Homer
fonte
1
Você testou essa linha shebang? Shebangs com vários argumentos não são portáveis. No Linux, #!a b cresultará em ["b c"], enquanto em outros sistemas, resultará em ["b", "c"].
precisa saber é o seguinte
1
Ele corrige seus próprios argumentos quando usado dessa maneira (caso contrário, a opção não seria muito útil).
Michael Homer
@MichaelHomer Eu preciso usar GNU parallelpara raspar páginas HTML. Poderia passar por esta discussão unix.stackexchange.com/questions/277609/...
Swatesh Pakhare