Come utilizzare l'elaborazione multi-thread negli script bash

Contenuti

gatto che gioca con il filo

La pianificazione multi-thread è sempre stata nell'interesse degli sviluppatori per aumentare le prestazioni delle applicazioni e massimizzare l'utilizzo delle risorse.. Questa guida ti introdurrà alle basi della codifica multithread di Bash.

Che cos'è programmazione multiprocesso?

Un'immagine vale più di mille parole, e questo è valido quando si tratta di mostrare la differenza tra la programmazione di un singolo (1) pianificazione thread e multi-thread (> 1) in bash:

dormire 1
dormire 1 & dormire 1

(Ultimo comando) Un semplice comando a una riga a due fili che eseguirà due processi di sospensione in parallelo, uno in sottofondo

Il nostro primo mini script a riga singola o l'impostazione della pianificazione multi-thread non avrebbe potuto essere più semplice; in prima linea, abbiamo dormito un secondo usando il sleep 1 comando. Per quanto riguarda l'utente, un singolo thread stava eseguendo un singolo sogno di un secondo.

Sulla seconda riga, abbiamo due comandi di sospensione da un secondo. Li uniamo usando a & separatore, che non solo funge da separatore tra i due sleep comandi, ma anche come prompt di Bash per avviare il primo comando in un thread in background.

Regolarmente, si finirebbe un comando usando un punto e virgola (;). Così facendo, il comando verrebbe eseguito e solo allora verrebbe passato al comando successivo che appare dopo il punto e virgola. Come esempio, in esecuzione sleep 1; sleep 1 ci vorrebbero poco più di due secondi: esattamente un secondo per il primo comando, un secondo per il secondo e una piccola quantità di sovraccarico del sistema per ciascuno dei due comandi.

Nonostante questo, invece di terminare un comando con un punto e virgola, puoi usare altri terminatori di comando che Bash riconosce come &, && e ||. il && la sintassi non ha nulla a che fare con la programmazione multithread, fai solo questo; procedere con l'esecuzione del secondo comando solo se il primo comando è andato a buon fine. il || È l'opposto di && ed eseguirà il secondo comando solo se il primo comando fallisce.

Tornando alla programmazione multithread, usando & poiché il nostro terminatore di comando avvierà una procedura in background eseguendo il comando che lo precede. Quindi procede immediatamente all'esecuzione del seguente comando nella shell corrente lasciando la procedura in background (ciao) gestito da solo.

Nell'output del comando possiamo vedere che una procedura viene avviata in background (come indicato [1] 445317 dove 445317 è l'ID della procedura o il PID della procedura in background appena avviata e [1] si afferma che questa è la nostra prima procedura di base) e successivamente terminato (come indicato [1]+ Done sleep 1).

Se si desidera visualizzare un ulteriore esempio di gestione dei processi in background, vedi il nostro post Bash Automation and Scripting Basics (Parte 3). Allo stesso tempo, I trucchi di terminazione della procedura Bash possono essere di interesse.

Ora dimostriamo che stiamo davvero eseguendo due sleep processi allo stesso tempo:

tempo di sonno 1; echo 'done'
time $(dormire 1 & dormire 1); eco 'fatto'

Eseguire due thread di sospensione in parallelo, con uno sullo sfondo, usando un sottolivello

Qui iniziamo il nostro sleep procedura bassa time e possiamo vedere come è stato eseguito esattamente il nostro comando a thread singolo 1.003 secondi prima che venisse restituito il prompt della riga di comando.

Nonostante questo, nel secondo esempio, ci è voluto più o meno lo stesso tempo (1,005 secondi) anche se stavamo correndo due periodi (e processi) sospensione, anche se non consecutivamente. Ancora una volta usiamo una procedura in background per il primo comando di sospensione, che porta a un'esecuzione (semi) parallelo, In altre parole, multiprocesso.

Usiamo anche un contenitore sottostrato ($(...)) intorno ai nostri due comandi onirici per combinarli sotto time. Come possiamo vedere il nostro done l'output è mostrato in 1.005 secondi e, perché, entrambi sleep 1 i comandi devono essere stati eseguiti contemporaneamente. Interessante è il piccolissimo aumento del tempo di elaborazione totale (0,002 secondi) che può essere facilmente spiegato dal tempo necessario per avviare un sottolivello e dal tempo necessario per avviare una procedura in background.

Gestione di processi multi-thread (e in sottofondo)

in bash, la codifica multi-thread coinvolgerà regolarmente thread in background da uno script principale di una riga o uno script bash completo. In sostanza, si può pensare alla codifica multi-thread in Bash come all'avvio di più thread in background. Quando si inizia a codificare utilizzando più thread, diventa subito chiaro che tali thread richiedono generalmente un po' di manipolazione. Come esempio, prendi l'esempio fittizio in cui iniziamo cinque periodi simultanei (e processi) di sonno in uno script Bash;

#!/bin/bash

sleep 10 & 
dormire 600 & 
dormire 1200 & 
dormire 1800 & 
dormire 3600 &

Esecuzione di cinque thread di sospensione paralleli in background da uno script

Quando iniziamo lo script (dopo averlo reso eseguibile utilizzando chmod +x rest.sh), non vediamo alcuna via d'uscita!! Anche se corriamo jobs (il comando che mostra i lavori in background in corso), il comando che mostra i lavori in background in corso. Come mai?

il comando che mostra i lavori in background in corso (In altre parole, il comando che mostra i lavori in background in corso) il comando che mostra i lavori in background in corso (il comando che mostra i lavori in background in corso; il comando che mostra i lavori in background in corso) che ha eseguito il sogno reale. comandi o li ha messi in background. Era piuttosto il (sub) shell che è iniziata quando ./rest.sh è stato giustiziato.

Cambiamo il nostro script aggiungendo jobs dentro lo script. Questo assicurerà che jobs corre dall'interno del (sub) shell ove pertinente, lo stesso in cui iniziarono i periodi (e processi) dormire.

Aggiungi il comando job nello script

Questa volta possiamo vedere l'elenco dei processi in background che stanno iniziando grazie a jobs comando alla fine dello script. Possiamo anche vedere i loro PID (identificatori di procedura). Questi PID sono molto importanti quando si tratta di gestire e gestire i processi in background.

Un altro modo per ottenere l'ID della procedura in background è interrogarlo immediatamente dopo aver posizionato un programma / procedura in background:

#!/bin/bash

sleep 10 & 
eco ${!}
dormire 600 & 
eco ${!}
dormire 1200 & 
eco ${!}
dormire 1800 & 
eco ${!}
dormire 3600 &
eco ${!}

Consulta il PID (ID processo) dell'ultimo processo in background da cui iniziare $ {!}

Simile al nostro jobs comando (con nuovi PID ora quando riavviamo il nostro rest.sh sceneggiatura), grazie alla bash ${!} Quando la variabile viene ripetuta, ora vedremo che tutti e cinque i PID vengono visualizzati quasi immediatamente dopo l'avvio dello script: più processi di sospensione sono stati inseriti in thread in background uno dopo l'altro.

The wait Command

Una volta avviati i nostri processi in background, non abbiamo altro da fare che aspettare che finiscano. Nonostante questo, quando ogni procedura in background sta eseguendo un'attività secondaria complessa, e abbiamo bisogno dello script principale (che ha avviato i processi in background) riprendere l'esecuzione quando uno o più processi in background terminano, abbiamo bisogno di codice aggiuntivo per gestirlo.

Espandiamo ora il nostro script con il wait comando per gestire i nostri thread in background:

#!/bin/bash

sleep 10 & 
T1=${!}
dormire 600 & 
T2=${!}
dormire 1200 & 
T3 = ${!}
dormire 1800 & 
T4 = ${!}
dormire 3600 &
T5 = ${!}

eco "Questo script è iniziato 5 thread in background attualmente in esecuzione con i PID ${T1}, ${T2}, ${T3}, ${T4}, ${T5}."
aspettare ${T1}
eco "Filo 1 (dormire 10) con PID ${T1} ha finito!"
aspettare ${T2}
eco "Filo 2 (dormire 600) con PID ${T2} ha finito!"

Qui estendiamo il nostro script con due wait comandi che attendono il completamento del PID collegato al primo e al secondo thread. Dopo 10 secondi, il nostro primo thread esiste e ne siamo informati. Passo dopo passo, questo script farà quanto segue: avvia cinque thread quasi contemporaneamente (anche se l'inizio dei thread è ancora sequenziale e non parallelo) dove ciascuno dei cinque sleepfunzionerà in parallelo.

Dopo, i rapporti di script principali (in sequenza) sul thread creato e, successivamente, attendi che l'id della procedura del primo thread finisca. Quando ciò accade, segnalerà in sequenza alla fine del primo thread e inizierà ad aspettare che il secondo thread finisca, eccetera.

Usando idiomi bash &, ${!} e il wait Il comando ci offre una grande flessibilità quando si tratta di eseguire più thread in parallelo (come thread di sfondo) in bash.

Fine

In questo post, Esploriamo le basi dello scripting multithread di Bash. Introdotto l'operatore della procedura in background (&) usando alcuni esempi facili da seguire che mostrano sia thread singolo che multi thread sleep comandi. Prossimo, discutiamo come gestire i processi in background attraverso idiomi bash comunemente usati. ${!} e wait. Esploriamo anche il jobs comando per visualizzare l'esecuzione del thread / processi in background.

Se ti è piaciuto leggere questo post, dai un'occhiata al nostro post Bash Procedure Termination Hacks.

Iscriviti alla nostra Newsletter

Non ti invieremo posta SPAM. Lo odiamo quanto te.