DevOps-bootcamp · Les

Workloads orkestreren met GNU parallel

Verdeel grote invoerreeksen over processorkernen met GNU parallel, jobsleuven en geordende resultaten.

Les 3 van 413 stappen

Workloads orkestreren met GNU parallel is een gratis DevOps-bootcamp-les op CoddyKit. Dit is les 3 van 4. Je kunt 3 lessen uit dit leerpad gratis volledig lezen — daarna ontgrendelt CoddyKit PRO alle lessen, plus praktische oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject DevOps-bootcamp. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus DevOps-bootcamp bevat in totaal 4 lessen.

Wat is GNU parallel en waarom zou je het gebruiken?

GNU parallel is een shellhulpmiddel waarmee je taken parallel kunt uitvoeren op één of meerdere machines. In plaats van een grote lijst met items één voor één in een for-lus te verwerken, verdeelt parallel het werk gelijktijdig over alle beschikbare CPU-kernen.

  • Snelheid: een taak die sequentieel 8 minuten duurt, kan op een machine met 8 kernen in ongeveer 1 minuut worden voltooid.
  • Eenvoud: het accepteert invoer uit stdin, bestanden of argumentenlijsten — handmatig procesbeheer is niet nodig.
  • Veiligheid: uitvoer van verschillende taken wordt gescheiden gehouden; resultaten worden nooit door elkaar heen weergegeven.

Installeer het met sudo apt install parallel (Debian/Ubuntu) of brew install parallel (macOS). Controleer de installatie met parallel --version.

Je eerste opdracht met parallel

De eenvoudigste vorm van parallel leest items uit stdin en voert voor elk item een opdracht uit. De tijdelijke aanduiding {} vertegenwoordigt het huidige invoeritem.

Het onderstaande voorbeeld comprimeert vijf logbestanden gelijktijdig met gzip. Zonder parallel zou elk bestand na het vorige worden gecomprimeerd. Met parallel worden maximaal N bestanden (waarbij N = het aantal CPU-kernen) tegelijkertijd gecomprimeerd.

#!/usr/bin/env bash
# Create sample files first
for i in 1 2 3 4 5; do
  dd if=/dev/urandom bs=1M count=2 of="log_${i}.txt" 2>/dev/null
done

# Compress all of them in parallel
ls log_*.txt | parallel gzip {}

echo "Done. Compressed files:"
ls log_*.txt.gz

Taakposities beheren met -j

Standaard voert parallel één taak per CPU-kern uit. Je kunt dit overschrijven met de vlag -j (of --jobs).

  • -j 4 — voer precies 4 taken tegelijk uit
  • -j 0 — voer evenveel taken uit als er invoeritems zijn (gebruik dit voorzichtig!)
  • -j 200% — voer twee keer zoveel taken uit als er CPU-kernen zijn (handig voor I/O-beperkt werk)
  • -j 50% — gebruik slechts de helft van de beschikbare kernen

Voor CPU-beperkte taken is -j $(nproc) vaak optimaal. Voor netwerk- of schijf-I/O-taken kun je het aantal kernen veilig overschrijden, omdat taken het grootste deel van de tijd wachten.

#!/usr/bin/env bash
# Show how many cores are available
echo "CPU cores: $(nproc)"

# Run 8 sleep jobs but limit to 3 at a time
# -j 3 means at most 3 jobs run simultaneously
seq 1 8 | parallel -j 3 'echo "Starting job {}"; sleep 1; echo "Done job {}"'

echo "All jobs finished."

Invoer uit bestanden en argumenten lezen

parallel is flexibel in de bron van de invoerlijst. Je bent niet beperkt tot doorsturen vanuit stdin.

  • Uit een bestand: parallel -a urls.txt wget {}
  • Inline argumentenlijst: parallel echo ::: apple banana cherry
  • Meerdere argumentbronnen (cartesisch product): parallel echo {1}-{2} ::: a b c ::: 1 2 — produceert a-1, a-2, b-1, b-2, c-1, c-2
  • Expliciet uit stdin: cat list.txt | parallel -j4 process {}

Het scheidingsteken ::: vertelt parallel dat de daaropvolgende waarden als argumentbron moeten worden gebruikt in plaats van stdin te lezen.

#!/usr/bin/env bash
# Inline list with :::
parallel echo 'Hello from {}' ::: Alice Bob Carol Dave

echo '---'

# Cartesian product: combine two lists
# Generates: dev-v1, dev-v2, prod-v1, prod-v2
parallel echo 'Deploy {1} to env {2}' ::: v1 v2 ::: dev prod

Tijdelijke aanduidingen: invoertokens bewerken

parallel biedt verschillende vervangingen voor tijdelijke aanduidingen waarmee je automatisch delen van de invoertekst kunt ophalen — erg handig wanneer de invoer bestandspaden bevat.

  • {} — het volledige invoeritem
  • {.} — invoer zonder de bestandsextensie (report.csv → report)
  • {/} — alleen de basisnaam (verwijdert het mappad)
  • {//} — alleen het mappad
  • {/.} — basisnaam zonder extensie

Hierdoor zijn aanroepen van basename / dirname binnen de taakopdracht niet nodig, waardoor pipelines overzichtelijker en sneller worden.

#!/usr/bin/env bash
# Demonstrate placeholder substitutions
parallel --dry-run 'convert {} -resize 800x600 {.}_thumb.jpg' \
  ::: /photos/vacation/beach.png /photos/work/team.png

# {.}  strips extension: /photos/vacation/beach
# Result command shown (--dry-run does NOT execute):
#  convert /photos/vacation/beach.png -resize 800x600 /photos/vacation/beach_thumb.jpg
#  convert /photos/work/team.png      -resize 800x600 /photos/work/team_thumb.jpg
echo 'No files were changed (dry run)'

Uitvoer op volgorde houden met --keep-order

Wanneer taken op verschillende momenten worden voltooid, verschijnt hun stdout-uitvoer in de volgorde waarin ze klaar zijn. Daardoor kunnen logboeken moeilijk leesbaar worden en kan het parseren door volgende verwerkingsstappen onbetrouwbaar worden.

Twee vlaggen bepalen de volgorde van de uitvoer:

  • --keep-order (-k) — geeft de uitvoer van elke taak weer in dezelfde volgorde als de invoer, zelfs als een latere taak eerder klaar is. De uitvoer wordt gebufferd totdat eerdere taken zijn voltooid.
  • --line-buffer — een middenweg: geeft volledige regels weer zodra ze binnenkomen, zonder op voltooiing van de taak te wachten, maar voegt nooit halfgeschreven regels samen.

Gebruik -k wanneer de volgende verwerkingsstap resultaten in invoervolgorde verwacht (bijvoorbeeld bij het opbouwen van een gesorteerd rapport). Laat deze vlag weg wanneer de volgorde niet belangrijk is en je resultaten zo snel mogelijk wilt zien.

#!/usr/bin/env bash
# Without -k: output order is unpredictable
echo '--- Without --keep-order ---'
seq 5 1 1 | parallel 'sleep 0.$((RANDOM % 5)); echo "Result for {}"'

echo

# With -k: output always appears as 5, 4, 3, 2, 1
echo '--- With --keep-order (-k) ---'
seq 5 1 1 | parallel -k 'sleep 0.$((RANDOM % 5)); echo "Result for {}"'

Uitvoer groeperen om vermenging te voorkomen

Zelfs met geordende uitvoer kunnen de regels van een taak die meerdere regels afdrukt, door elkaar komen te staan met regels van een andere taak die tegelijkertijd wordt uitgevoerd. parallel lost dit automatisch op door de volledige standaarduitvoer en standaardfoutuitvoer van elke taak te bufferen en deze vervolgens als één atomair blok af te drukken zodra de taak is voltooid.

Dit gedrag staat standaard aan. Je kunt het uitschakelen met --ungroup als je uitvoer direct wilt streamen, bijvoorbeeld bij langlopende taken met voortgangsbalken. De uitvoer kan dan echter weer door elkaar komen te staan.

  • Standaard: uitvoer wordt per taak gegroepeerd — veilig om te parseren.
  • --ungroup: uitvoer wordt direct gestreamd — geschikt voor interactieve bewaking.
  • --line-buffer: compromis — regels worden nooit opgesplitst, maar taken kunnen bij de regeleinden door elkaar lopen.

Argumenten doorgeven binnen shellfuncties

Soms bestaat het werk dat je wilt parallelliseren uit meer dan één opdracht — het is een shellfunctie met meerdere stappen. Je kunt een functie aan parallel doorgeven met export -f in combinatie met env_parallel, of door bash -c rechtstreeks aan te roepen.

De veiligste draagbare aanpak voor complexe taken is het patroon bash -c '...'. De tijdelijke aanduiding {} wordt doorgegeven als $1 wanneer je afsluit met _ {}.

#!/usr/bin/env bash
# Define a multi-step processing function
process_item() {
  local item="$1"
  echo "[START] $item"
  # Simulate two steps
  sleep 0.2
  local result=$(echo "$item" | tr '[:lower:]' '[:upper:]')
  echo "[END]   $item -> $result"
}

export -f process_item

# Run the function in parallel for each input
echo 'alpha beta gamma delta epsilon' | tr ' ' '\n' \
  | parallel -j 3 process_item {}

Beperken en opnieuw proberen met --delay en --retries

Wanneer je externe diensten (API's, externe servers en databases) parallel aanspreekt, heb je vaak snelheidsbeperking en fouttolerantie nodig.

  • --delay N — wacht N seconden tussen het starten van elke nieuwe taak (decimale waarden zoals 0.5 zijn toegestaan). Voorkomt dat een dienst wordt overspoeld.
  • --retries N — als een taak eindigt met een status die niet nul is, probeer je deze maximaal N keer opnieuw voordat je opgeeft. Elke nieuwe poging telt als een nieuwe taakpositie.
  • --timeout N — beëindig een taak als deze langer dan N seconden actief is. In combinatie met --retries worden vastgelopen taken hiermee netjes afgehandeld.

Voorbeeld: 50 URL's downloaden met maximaal 4 gelijktijdige verbindingen, een opstartvertraging van 0,5 seconde tussen starts en 3 nieuwe pogingen bij fouten.

#!/usr/bin/env bash
# Simulate downloading URLs with throttling and retries
# (using echo instead of curl so this is self-contained)

download_url() {
  local url="$1"
  # Randomly fail ~30% of the time to demo --retries
  if (( RANDOM % 10 < 3 )); then
    echo "FAIL: $url" >&2
    return 1
  fi
  echo "OK:   $url downloaded"
}

export -f download_url

printf 'https://example.com/file%d\n' $(seq 1 10) \
  | parallel -j 4 --delay 0.2 --retries 3 download_url {}

echo 'All downloads attempted.'

Werk verdelen over externe hosts met --sshloginfile

parallel kan taken transparant via SSH over externe machines verdelen. Daarmee fungeert het als een lichtgewicht hulpmiddel voor clusterberekeningen, zonder speciale clustersoftware.

  • --sshlogin user@host — voer taken uit op een specifieke externe host.
  • --sshloginfile machines.txt — lees een lijst met hosts uit een bestand, één per regel. Gebruik : als speciale vermelding om ook de lokale machine te gebruiken.
  • --transfer — kopieer het invoerbestand vóór de verwerking naar de externe host.
  • --return {} — kopieer het resultaatbestand terug nadat de taak is voltooid.
  • --cleanup — verwijder overgezette bestanden na het ophalen van de externe host.

Op de externe host moet parallel zijn geïnstalleerd en verificatie met SSH-sleutels zijn geconfigureerd, zodat er niet om een wachtwoord wordt gevraagd.

Voortgang melden en loggen

Bij langlopende werklasten is het essentieel om de voortgang te bewaken en achteraf fouten te kunnen vaststellen.

  • --progress — drukt een actuele samenvattingsregel af met het aantal actieve, voltooide en resterende taken.
  • --eta — schat de resterende tijd op basis van de gemiddelde taakduur tot nu toe.
  • --joblog results.log — schrijft een door tabs gescheiden logbestand met één rij per voltooide taak, inclusief afsluitcode, uitvoeringsduur en de uitgevoerde opdracht. Onmisbaar voor het controleren van fouten.
  • --resume --joblog results.log — slaat taken over die al in het logbestand staan, met afsluitcode 0. Als een batchuitvoering wordt onderbroken, kun je deze hervatten zonder geslaagd werk opnieuw uit te voeren.

De combinatie --joblog + --resume is een van de krachtigste functies van GNU parallel voor robuuste productieprocessen.

#!/usr/bin/env bash
LOGFILE="/tmp/parallel_demo_$$.log"

# Run jobs and record results to a log
seq 1 12 | parallel \
  --jobs 4 \
  --progress \
  --joblog "$LOGFILE" \
  'sleep 0.1; echo "Processed item {}"'

echo
echo '=== Job Log (first 5 entries) ==='
head -6 "$LOGFILE"

# Show only failed jobs (exit value != 0)
echo '=== Failed jobs ==='
awk 'NR>1 && $7 != 0 { print $0 }' "$LOGFILE" || echo '(none)'

rm -f "$LOGFILE"

Kennischeck: opties voor taakposities

Test je begrip van de manier waarop parallel gelijktijdige uitvoering beheert.

Samenvatting van de les: werklasten orkestreren met GNU parallel

Je hebt de belangrijkste hulpmiddelen behandeld om grote invoerverzamelingen over CPU-kernen te verdelen met GNU parallel. Dit zijn de belangrijkste punten:

  • Basisgebruik: stuur een lijst door naar parallel command {} — {} wordt vervangen door elk invoeritem.
  • Taakposities (-j): beheer gelijktijdige uitvoering nauwkeurig — gebruik het aantal kernen voor CPU-intensief werk en hogere percentages voor werk dat door invoer en uitvoer wordt beperkt.
  • Tijdelijke aanduidingen ({.}, {/}, {//}, {/.}) halen padonderdelen netjes uit zonder extra opdrachten.
  • Uitvoerbeheer: -k behoudt de volgorde van de invoer; standaardgroepering voorkomt regels die door elkaar komen te staan; --ungroup zorgt voor directe streaming.
  • Robuustheid: --retries, --timeout en --delay maken parallelle processen bestand tegen onbetrouwbare taken en snelheidsbeperkingen.
  • Controleerbaarheid: --joblog registreert het resultaat van elke taak; met --resume kun je na een onderbreking verdergaan waar je was gebleven.
  • Uitschalen: --sshloginfile verdeelt taken via SSH over externe machines, zonder extra clusterinfrastructuur.

Als je deze opties beheerst, verandert parallel in een orkestrator voor werklasten op productieniveau, die rechtstreeks in je shell is ingebouwd.

Gratis beginnen

Leer DevOps-bootcamp met een AI-tutor — gratis

Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.

Cursussen
142
Lessen
568

Veelgestelde vragen

Is de les “Workloads orkestreren met GNU parallel” gratis?

Ja — je kunt hier op het web alle 3 lessen van het leerpad DevOps-bootcamp, waaronder “Workloads orkestreren met GNU parallel”, gratis volledig lezen. Daarna ontgrendelt CoddyKit PRO alle lessen, plus interactieve oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. De cursus DevOps-bootcamp bevat in totaal 4 lessen.

Wat leer ik in “Workloads orkestreren met GNU parallel”?

Verdeel grote invoerreeksen over processorkernen met GNU parallel, jobsleuven en geordende resultaten. Je oefent met DevOps-bootcamp door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.

Heb ik ervaring nodig om met DevOps-bootcamp te beginnen?

Ervaring vooraf is niet nodig. DevOps-bootcamp op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 3 van 4.

Hoe lang duurt de les “Workloads orkestreren met GNU parallel”?

De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.

Kan ik code schrijven en uitvoeren in deze les over DevOps-bootcamp?

Ja. Elke les over DevOps-bootcamp bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.

Alle lessen in deze cursus

  1. Scripts profileren en overbodige subshells vermijden
  2. Parallelisme met xargs -P en achtergrondtaken
  3. Workloads orkestreren met GNU parallel
  4. Streaming-pipelines en named pipes voor doorvoer
← Terug naar DevOps-bootcamp