So verwenden Sie die Multithread-Verarbeitung in Bash-Skripten

Inhalt

Katze spielt mit Garn

Multithread-Scheduling war schon immer im Interesse von Entwicklern, um die Anwendungsleistung zu steigern und die Ressourcennutzung zu maximieren.. Dieser Leitfaden führt Sie in die Grundlagen der Multithread-Codierung von Bash ein.

Was ist es Multiprozessprogrammierung?

Ein Bild sagt mehr als tausend Worte, und dies gilt, wenn es darum geht, den Unterschied zwischen der Programmierung einer Single zu zeigen (1) Thread- und Multi-Thread-Scheduling (> 1) in bash:

Schlaf 1
Schlaf 1 & Schlaf 1

(Letzter Befehl) Ein einfacher zweiadriger einzeiliger Befehl, der zwei Suspend-Prozesse parallel ausführt, einer im hintergrund

Unser erstes einzeiliges Miniskript oder Multithreaded-Planungs-Setup hätte nicht einfacher sein können; an vorderster Front, Wir haben eine Sekunde geschlafen mit dem sleep 1 Befehl. In Bezug auf den Benutzer, ein einzelner Thread hat einen einzigen Ein-Sekunden-Traum ausgeführt.

In der zweiten Zeile, Wir haben zwei Suspend-Befehle von einer Sekunde. Wir verbinden sie mit a & Separator, die nicht nur als Trennzeichen zwischen den beiden fungiert sleep Befehle, aber auch als Bash-Eingabeaufforderung, um den ersten Befehl in einem Hintergrundthread zu starten.

Regelmäßig, man würde einen Befehl mit einem Semikolon beenden (;). Dabei, der Befehl würde ausgeführt und erst dann an den nächsten Befehl übergeben, der nach dem Semikolon erscheint. Als Beispiel, Laufen sleep 1; sleep 1 es würde etwas mehr als zwei Sekunden dauern: genau eine Sekunde für den ersten Befehl, eine Sekunde für den zweiten und ein kleiner System-Overhead für jeden der beiden Befehle.

Trotz dieses, anstatt einen Befehl mit einem Semikolon zu beenden, Sie können andere Befehlsterminatoren verwenden, die Bash als &, && und ||. das && Syntax hat nichts mit Multithread-Programmierung zu tun, mach das einfach; Fahren Sie mit der Ausführung des zweiten Befehls nur fort, wenn der erste Befehl erfolgreich war. das || Es ist das Gegenteil von && und es wird den zweiten Befehl nur ausführen, wenn der erste Befehl fehlgeschlagen ist.

Zurück zur Multithread-Programmierung, mit & da unser Befehlsterminator eine Hintergrundprozedur startet, indem er den vorhergehenden Befehl ausführt. Es führt dann sofort den folgenden Befehl in der aktuellen Shell aus, während die Hintergrundprozedur (hallo) von selbst laufen.

In der Ausgabe des Befehls sehen wir, dass im Hintergrund eine Prozedur gestartet wird (wie angezeigt [1] 445317 wo 445317 die Prozedur-ID oder PID der neu gestarteten Hintergrundprozedur ist und [1] es wird festgestellt, dass dies unser erstes Hintergrundverfahren ist) und anschließend beendet (wie angezeigt [1]+ Done sleep 1).

Wenn Sie ein zusätzliches Beispiel für die Verarbeitung von Hintergrundprozessen sehen möchten, siehe unseren Beitrag Bash Automation and Scripting Basics (Teil 3). Zur selben Zeit, Bash-Verfahrens-Beendigungstricks könnten von Interesse sein.

Lassen Sie uns nun zeigen, dass wir tatsächlich zwei sleep Prozesse zur gleichen Zeit:

Zeit schlafen 1; echo 'done'
time $(Schlaf 1 & Schlaf 1); echo 'fertig'

Führen Sie zwei Hängende Threads parallel aus, mit einem im Hintergrund, mit einer Unterschicht

Hier starten wir unsere sleep niedrige Prozedur time und wir können sehen, wie unser Single-Thread-Befehl genau gelaufen ist 1.003 Sekunden bevor die Befehlszeilenaufforderung zurückgegeben wurde.

Trotz dieses, im zweiten Beispiel, hat ungefähr die gleiche zeit gedauert (1,005 Sekunden) obwohl wir zwei stunden gelaufen sind (und Prozesse) Suspension, auch wenn nicht hintereinander. Wieder verwenden wir eine Hintergrundprozedur für den ersten Suspend-Befehl, zu einer Hinrichtung führen (halb) parallel, Mit anderen Worten, Multiprozess.

Wir verwenden auch einen Sublayer-Container ($(...)) um unsere beiden Traumbefehle um sie unter zu kombinieren time. Wie können wir unsere sehen? done die Ausgabe wird angezeigt in 1.005 Sekunden und, da, beide sleep 1 die Befehle müssen gleichzeitig ausgeführt worden sein. Interessant ist die sehr geringe Erhöhung der Gesamtbearbeitungszeit (0,002 Sekunden) was leicht erklärt werden kann durch die Zeit zum Starten einer Unterebene und die Zeit zum Starten einer Hintergrundprozedur.

Verwalten von Multithread-Prozessen (und im Hintergrund)

In bash, Multithread-Codierung umfasst regelmäßig Hintergrundthreads aus einem einzeiligen Hauptskript oder einem vollständigen Bash-Skript. Im Wesentlichen, man kann sich Multithread-Codierung in Bash so vorstellen, als würde man mehrere Hintergrundthreads starten. Wenn man mit dem Codieren mit mehreren Threads beginnt, Es wird schnell klar, dass solche Threads in der Regel etwas Handhabung erfordern. Als Beispiel, Nehmen wir das fiktive Beispiel, bei dem wir fünf gleichzeitige Perioden beginnen (und Prozesse) des Schlafes in einem Bash-Skript;

#!/bin/bash

sleep 10 & 
Schlaf 600 & 
Schlaf 1200 & 
Schlaf 1800 & 
Schlaf 3600 &

Ausführen von fünf parallelen Standby-Threads im Hintergrund aus einem Skript

Wenn wir das Skript starten (Nachdem Sie es mit chmod +x rest.sh), wir sehen keinen Ausweg!! Auch wenn wir laufen jobs (der Befehl, der die laufenden Hintergrundjobs anzeigt), Kein Ausgang. Wieso den?

Der Grund dafür ist die Shell, die zum Starten dieses Skripts verwendet wurde (Mit anderen Worten, el Shell tatsächlich) nicht die gleiche Schale (nicht der gleiche Faden; anfangen, in Begriffen von Unterschichten als Fäden an und für sich zu denken) wer hat den königlichen traum ausgeführt. Befehle oder in den Hintergrund gestellt. Es war eher der (unter) Shell, die begann, als ./rest.sh wurde ausgeführt.

Lassen Sie uns unser Skript ändern, indem wir hinzufügen jobs im Skript. Dadurch wird sichergestellt, dass jobs läuft aus dem (unter) Shell, wo relevant, das gleiche, in dem die Perioden begannen (und Prozesse) Schlaf.

Auftragsbefehl im Skript hinzufügen

Diesmal können wir die Liste der Hintergrundprozesse sehen, die dank . starten jobs Befehl am Ende des Skripts. Wir können auch ihre PIDs sehen (Verfahrenskennungen). Diese PIDs sind sehr wichtig, wenn es um die Handhabung und Verwaltung von Hintergrundprozessen geht.

Eine andere Möglichkeit, die ID der Hintergrundprozedur zu erhalten, besteht darin, sie sofort nach dem Platzieren eines Programms abzufragen / Hintergrundverfahren:

#!/bin/bash

sleep 10 & 
Echo ${!}
Schlaf 600 & 
Echo ${!}
Schlaf 1200 & 
Echo ${!}
Schlaf 1800 & 
Echo ${!}
Schlaf 3600 &
Echo ${!}

Konsultieren Sie die PID (Prozess ID) des zuletzt gestarteten Hintergrundprozesses $ {!}

Ähnlich wie unser jobs Befehl (mit neuen PIDs jetzt, wenn wir unsere neu starten rest.sh Skript), danke an die bash ${!} Wenn die Variable wiederholt wird, Jetzt werden wir sehen, dass alle fünf PIDs fast unmittelbar nach dem Start des Skripts angezeigt werden: mehrere Suspend-Prozesse wurden nacheinander in Hintergrundthreads gelegt.

The wait Command

Sobald wir unsere Hintergrundprozesse gestartet haben, Wir haben nichts anderes zu tun, als zu warten, bis sie fertig sind. Trotz dieses, wenn jede Hintergrundprozedur eine komplexe Teilaufgabe ausführt, und wir brauchen das Hauptskript (die die Hintergrundprozesse gestartet haben) Fortsetzen der Ausführung, wenn einer oder mehrere der Hintergrundprozesse beendet werden, wir brauchen zusätzlichen Code, um dies zu handhaben.

Erweitern wir unser Skript jetzt mit dem wait Befehl, um unsere Hintergrundthreads zu verarbeiten:

#!/bin/bash

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

Echo "Dieses Skript hat begonnen 5 Hintergrundthreads, die derzeit mit PIDs ausgeführt werden ${T1}, ${T2}, ${T3}, ${T4}, ${T5}."
Warten ${T1}
Echo "Gewinde 1 (Schlaf 10) mit PID ${T1} hat beendet!"
Warten ${T2}
Echo "Gewinde 2 (Schlaf 600) mit PID ${T2} hat beendet!"

Hier erweitern wir unser Skript um zwei wait Befehle, die darauf warten, dass die an den ersten und zweiten Thread angehängte PID beendet ist. Nach 10 Sekunden, unser erster Thread existiert und wir werden darüber informiert. Schritt für Schritt, Dieses Skript wird Folgendes tun: fünf Threads fast gleichzeitig starten (obwohl der Start der Threads selbst noch sequentiell und nicht parallel ist) wo jeder der fünf sleepläuft parallel.

Nach, die wichtigsten Skriptberichte (der Reihe nach) über den erstellten Thread und, anschließend, warten, bis die Prozedur-ID des ersten Threads beendet ist. Wenn das passiert, berichtet sequentiell über das Ende des ersten Threads und beginnt zu warten, bis der zweite Thread beendet ist, etc.

Bash-Idiome verwenden &, ${!} und der wait Der Befehl gibt uns große Flexibilität, wenn es darum geht, mehrere Threads parallel auszuführen (als Hintergrundthreads) in bash.

Ende

In diesem Beitrag, Wir erkunden die Grundlagen von Bash Multithreaded Scripting. Einführung des Hintergrundverfahrensoperators (&) anhand einiger leicht verständlicher Beispiele, die sowohl ein- als auch mehrgängig zeigen sleep Befehle. Nächste, wir diskutieren, wie man Hintergrundprozesse durch häufig verwendete Bash-Idiome handhabt. ${!} und wait. Wir erkunden auch die jobs Befehl zum Anzeigen der Thread-Ausführung / Hintergrundprozesse.

Wenn es dir Spaß gemacht hat diesen Beitrag zu lesen, Werfen Sie einen Blick auf unseren Beitrag Bash Procedure Termination Hacks.

Abonniere unseren Newsletter

Wir senden Ihnen keine SPAM-Mail. Wir hassen es genauso wie du.