Multithreading / Forking in uno script bash


9

Ho scritto uno script bash che è nel seguente 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."

Il whileloop leggerà $inFile, eseguirà alcune attività sulla linea e scaricherà il risultato $outFile.

Poiché le $inFilerighe sono oltre 3500, lo script impiegherà 6-7 ore per l'esecuzione completa. Per ridurre al minimo questo tempo, sto pensando di usare il multi-threading o il fork in questo script. Se creo 8 processi figlio, 8 linee da $inFileverranno elaborate contemporaneamente.

Come si può fare?


Fai attenzione: diversi script dovranno scrivere su diversi file. Anche il tuo script come scritto cancella il file di input come prima azione!
pjc50,

Risposte:


10

GNUparallel è fatto proprio per questo genere di cose. È possibile eseguire lo script più volte contemporaneamente, con dati diversi dall'input inseriti per ciascuno di essi:

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

Per impostazione predefinita, genererà i processi in base al numero di processori sul tuo sistema, ma puoi personalizzarlo con -j N.

Un trucco particolarmente accurato è la funzione avvolgente shebang. Se cambi la prima riga del tuo script Bash in:

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

e fornire i dati su input standard quindi accadrà automaticamente. Questo è meno utile quando hai un codice di pulizia che deve essere eseguito alla fine, cosa che potresti fare.

Ci sono un paio di cose da notare. Uno è che taglierà i tuoi input in blocchi sequenziali e li userà uno alla volta - non interlaccia le linee. L'altro è che quei pezzi sono divisi per dimensione, indipendentemente da quanti record ci sono. È possibile utilizzare --block Nper impostare una dimensione di blocco diversa in byte. Nel tuo caso, non più di un ottavo della dimensione del file dovrebbe essere giusto. Il tuo file sembra che potrebbe essere abbastanza piccolo da finire tutto in un unico blocco altrimenti, il che vanificherebbe lo scopo.

Ci sono molte opzioni per diversi casi d'uso, ma il tutorial copre abbastanza bene le cose. Le opzioni che potrebbero interessarti sono anche --round-robine --group.


1
Hai testato quella linea Shebang? Shebang con argomenti multipli non sono portabili. Su Linux, #!a b csi verificherà ["b c"], mentre su altri sistemi, si tradurrà in ["b", "c"].
nyuszika7h

1
Sostituisce i propri argomenti quando viene utilizzato in questo modo (altrimenti l'opzione non sarebbe molto utile).
Michael Homer,

@MichaelHomer Devo usare GNU parallelper raschiare le pagine HTML. Potresti per favore passare attraverso questa discussione unix.stackexchange.com/questions/277609/…
Swatesh Pakhare,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.