GNU/Linux >> Linux Esercitazione >  >> Linux

Impara gli script Bash multi-threading con GNU Parallel

Se sei stanco dei tuoi script Bash che impiegano un'eternità per essere eseguiti, questo tutorial è per te. Spesso puoi eseguire Bash script in parallelo, il che può accelerare notevolmente il risultato. Come? Usando l'utilità GNU Parallel, chiamata anche semplicemente Parallel, con alcuni pratici esempi di GNU Parallel!

Parallel esegue gli script Bash in parallelo tramite un concetto chiamato multi-threading. Questa utility ti consente di eseguire diversi lavori per CPU invece di uno solo, riducendo il tempo per eseguire uno script.

In questo tutorial imparerai gli script Bash multi-thread con un sacco di fantastici esempi di GNU Parallel!

Prerequisiti

Questo tutorial sarà pieno di dimostrazioni pratiche. Se intendi seguire, assicurati di avere quanto segue:

  • Un computer Linux. Qualsiasi distribuzione funzionerà. Il tutorial utilizza Ubuntu 20.04 in esecuzione su Windows Subsystem for Linux (WSL).
  • Accesso effettuato con un utente con privilegi sudo.

Installazione di GNU Parallel

Per iniziare ad accelerare gli script Bash con il multithreading, devi prima installare Parallel. Quindi iniziamo scaricandolo e facendolo installare.

1. Apri un terminale Bash.

2. Esegui wget per scaricare il pacchetto Parallel. Il comando seguente scarica l'ultima versione (parallel-latest ) nella directory di lavoro corrente.

wget https://ftp.gnu.org/gnu/parallel/parallel-latest.tar.bz2

Se preferisci usare una versione precedente di GNU Parallel, puoi trovare tutti i pacchetti sul sito ufficiale di download.

3. Ora, esegui il comando tar di seguito per annullare l'archiviazione del pacchetto appena scaricato.

Di seguito, il comando utilizza il x flag per estrarre l'archivio, j per specificare che ha come target un archivio con un .bz2 estensione e f per accettare un file come input del comando tar. sudo tar -xjf parallel-latest.tar.bz2

sudo tar -xjf parallel-latest.tar.bz2

Ora dovresti avere una directory chiamata parallel- con il mese, il giorno e l'anno dell'ultima versione.

4. Passare alla cartella dell'archivio del pacchetto con cd . In questo tutorial, la cartella dell'archivio del pacchetto è denominata parallel-20210422 , come mostrato di seguito.

5. Quindi, compila e installa il binario GNU Parallel eseguendo i seguenti comandi:

./configure
 make
 make install

Ora, verifica che Parallel sia installato correttamente controllando la versione installata.

parallel --version

Quando esegui Parallel per la prima volta, potresti anche vedere un paio di righe spaventose che mostrano testo come perl: warning: . Questi messaggi di avviso indicano che Parallel non è in grado di rilevare le impostazioni locali e della lingua correnti. Ma per ora non preoccuparti di quegli avvisi. Imparerai come correggere questi avvisi in seguito.

Configurazione di GNU Parallel

Ora che Parallel è installato, puoi usarlo subito! Ma prima, è importante configurare alcune impostazioni minori prima di iniziare.

Mentre sei ancora nel tuo terminale Bash, accetta il permesso di ricerca accademica GNU Parallel dicendo a Parallel che lo citerai in qualsiasi ricerca accademica specificando il citation parametro seguito da will cite .

Se non vuoi supportare GNU oi suoi manutentori, non è necessario accettare di citare per usare GNU Parallel.

parallel --citation
will cite

Modificare le impostazioni locali impostando le seguenti variabili di ambiente eseguendo le righe di codice seguenti. L'impostazione di variabili di ambiente e lingua come questa non è un requisito. Ma GNU Parallel li controlla ogni volta che viene eseguito.

Se le variabili d'ambiente non esistono, Parallel se ne lamenterà ogni volta come hai visto nella sezione precedente.

Questo tutorial presuppone che tu parli inglese. Sono supportate anche altre lingue.

export LC_ALL=C man
export LANGUAGE=en_US
export LANG=en_US.UTF-8

Esecuzione di comandi shell ad hoc

Iniziamo ora a usare GNU Parallel! Per cominciare, imparerai la sintassi di base. Una volta che avrai preso dimestichezza con la sintassi, in seguito entrerai in alcuni pratici esempi di GNU Parallel.

Per iniziare, copriamo un esempio semplicissimo di fare eco ai numeri 1-5.

1. Nel tuo terminale Bash, esegui i seguenti comandi. Emozionante, vero? Bash usa il comando echo per inviare i numeri 1-5 al terminale. Se inserisci ciascuno di questi comandi in uno script, Bash li eseguirà in sequenza, aspettando che il precedente finisca.

In questo esempio, stai eseguendo cinque comandi che non richiedono molto tempo. Ma immagina se quei comandi fossero script Bash in realtà hanno fatto qualcosa di utile ma hanno impiegato un'eternità per essere eseguiti?

 echo 1
 echo 2
 echo 3
 echo 4
 echo 5

Ora, esegui ciascuno di questi comandi contemporaneamente con Parallel come di seguito. In questo esempio, Parallel esegue il comando echo e designato da ::: , passa a quel comando gli argomenti, 1 , 2 , 3 , 4 , 5 . I tre due punti indicano a Parallel che stai fornendo input tramite la riga di comando anziché tramite la pipeline (più avanti).

Nell'esempio seguente, hai passato un singolo comando a Parallel senza opzioni. Qui, come tutti gli esempi di Parallel, Parallel ha avviato un nuovo processo per ogni comando utilizzando un core CPU diverso.

# From the command line
 parallel echo ::: 1 2 3 4 5

Tutti i comandi Parallel seguono la sintassi parallel [Options] .

3. Per dimostrare la ricezione parallela dell'input dalla pipeline Bash, crea un file chiamato count_file.txt come di seguito. Ogni numero rappresenta l'argomento che passerai al comando echo.

 1
 2
 3
 4
 5

4. Ora esegui cat comando per leggere quel file e passare l'output a Parallel, come mostrato di seguito. In questo esempio, il {} rappresenta ogni argomento (1-5) che verrà passato a Parallel.

# From the pipeline cat count_file.txt | parallel echo {}

Confronto tra Bash e GNU Parallel

In questo momento, l'utilizzo di Parallel potrebbe sembrare un modo complicato per eseguire i comandi Bash. Ma il vero vantaggio per te è il risparmio di tempo. Ricorda, Bash funzionerà su un solo core della CPU mentre GNU Parallel funzionerà su più core contemporaneamente.

1. Per dimostrare la differenza tra i comandi Bash sequenziali e Parallel, crea uno script Bash chiamato test.sh con il seguente codice. Crea questo script nella stessa directory in cui hai creato count_file.txt in precedenza.

Lo script Bash di seguito legge count_file.txt file, dorme per 1, 2, 3, 4 e 5 secondi, fa eco alla durata della sospensione sul terminale e termina.

#!/bin/bash
 nums=$(cat count_file.txt) # Read count_file.txt
 for num in $nums           # For each line in the file, start a loop
 do
     sleep $num             # Read the line and wait that many seconds
     echo $num              # Print the line
 done

2. Ora esegui lo script usando il time comando per misurare quanto tempo impiega lo script per essere completato. Ci vorranno 15 secondi.

time ./test.sh

3. Ora usa il time comando di nuovo per eseguire la stessa attività, ma questa volta utilizzare Parallel per farlo.

Il comando seguente esegue la stessa attività ma questa volta, invece di attendere il completamento del primo ciclo prima di iniziare il successivo, ne eseguirà uno su ciascun core della CPU e ne avvierà il maggior numero possibile contemporaneamente.

time cat count_file.txt | parallel "sleep {}; echo {}"

Conosci la corsa a secco!

È giunto il momento di approfondire alcuni esempi di GNU Parallel nel mondo reale. Ma, prima di farlo, dovresti prima conoscere il --dryrun bandiera. Questo flag è utile quando vuoi vedere cosa accadrà senza che Parallel lo faccia effettivamente.

Il --dryrun flag può essere il controllo di integrità finale prima di eseguire un comando che non si comporta come pensavi. Sfortunatamente, se inserisci un comando che danneggerebbe il tuo sistema, l'unica cosa che GNU Parallel ti aiuterà a fare è danneggiarlo più velocemente!

parallel --dryrun "rm rf {}"

Esempio GNU Parallel n. 1:download di file dal Web

Per questa attività, scaricherai un elenco di file da vari URL sul Web. Ad esempio, questi URL potrebbero rappresentare pagine Web che desideri salvare, immagini o persino un elenco di file da un server FTP.

Per questo esempio, scaricherai un elenco di pacchetti di archivio (e i file SIG) dal server FTP di GNU Parallel.

1. Crea un file chiamato download_items.txt, prendi alcuni link per il download dal sito ufficiale di download e aggiungili al file separati da una nuova riga.

 https://ftp.gnu.org/gnu/parallel/parallel-20120122.tar.bz2
 https://ftp.gnu.org/gnu/parallel/parallel-20120122.tar.bz2.sig
 https://ftp.gnu.org/gnu/parallel/parallel-20120222.tar.bz2
 https://ftp.gnu.org/gnu/parallel/parallel-20120222.tar.bz2.sig

Potresti risparmiare un po' di tempo utilizzando la libreria Beautiful Soup di Python per raschiare tutti i link dalla pagina di download.

2. Leggi tutti gli URL da download_items.txt file e passarli a Parallel, che invocherà wget e passa ogni URL.

cat download_items.txt | parallel wget {}

Non dimenticare che {} in un comando parallelo è un segnaposto per la stringa di input!

3. Forse hai bisogno di controllare il numero di thread che GNU Parallel usa contemporaneamente. In tal caso, aggiungi il --jobs o -j parametro al comando. Il --jobs parametro limita il numero di thread che possono essere eseguiti contemporaneamente al numero specificato.

Ad esempio, per limitare Parallel al download di cinque URL alla volta, il comando sarebbe simile al seguente:

#!/bin/bash
 cat download_items.txt | parallel --jobs 5 wget {}

Il --jobs parametro nel comando precedente può essere regolato per scaricare un numero qualsiasi di file, a condizione che il computer su cui si esegue abbia così tante CPU per elaborarli.

4. Per dimostrare l'effetto del --jobs parametro, ora regola il conteggio dei lavori ed esegui il time comando per misurare quanto tempo impiega ogni corsa.

 time cat download_items.txt | parallel --jobs 5 wget {}
 time cat download_items.txt | parallel --jobs 10 wget {}

Esempio GNU Parallel n. 2:decomprimere i pacchetti di archivio

Ora che hai scaricato tutti questi file di archivio dall'esempio precedente, ora devi annullarne l'archiviazione.

Mentre ci si trova nella stessa directory dei pacchetti di archivio, eseguire il seguente comando Parallel. Notare l'uso del carattere jolly (* ). Poiché questa directory contiene entrambi i pacchetti di archivio e i file SIG, devi dire a Parallel di elaborare solo .tar.bz2 file.

sudo parallel tar -xjf ::: *.tar.bz2

Bonus! Se stai usando GNU parallel in modo interattivo (non in uno script), aggiungi il --bar flag per fare in modo che Parallel ti mostri una barra di avanzamento mentre l'attività è in esecuzione.

Esempio GNU Parallel n. 3:rimozione di file

Se hai seguito gli esempi uno e due, ora dovresti avere molte cartelle nella tua directory di lavoro che occupano spazio. Quindi rimuoviamo tutti quei file in parallelo!

Per rimuovere tutte le cartelle che iniziano con parallelo- usando Parallel, elenca tutte le cartelle con ls -d e reindirizza ciascuno di quei percorsi di cartella a Parallel, invocando rm -rf su ciascuna cartella, come mostrato di seguito.

Ricorda il --dryrun bandiera!

ls -d parallel-*/ | parallel "rm -rf {}"

Conclusione

Ora puoi automatizzare le attività con Bash e risparmiare molto tempo. Quello che scegli di fare con quel tempo dipende da te. Se risparmiare tempo significa lasciare il lavoro un po' presto o leggere un altro post del blog ATA, è tempo di tornare ai tuoi tempi.

Ora pensa a tutti gli script di lunga durata nel tuo ambiente. Quali puoi velocizzare con Parallel?


Linux
  1. Eseguire script Bash all'ingresso di una directory?

  2. Bash Istruzione If-Else con esempi

  3. Parametri speciali di Bash spiegati con 4 script di shell di esempio

  4. Parametri posizionali di Bash spiegati con 2 script di shell di esempio

  5. Alias ​​con variabile in bash

Impara Linux con Raspberry Pi

Scrivere commenti negli script Bash

Come creare finestre di dialogo della GUI negli script Bash con Whiptail in Linux

Gestione degli errori negli script Bash

Come creare documenti con gli script Bash

Come lavorare con l'istruzione Case negli script Bash