DevOps-bootcamp · leksjon

Parallellitet med xargs -P og bakgrunnsjobber

Kjør uavhengige oppgaver samtidig ved hjelp av parallellmodus i xargs og administrerte puljer med bakgrunnsjobber.

Leksjon 2 av 413 trinn

Parallellitet med xargs -P og bakgrunnsjobber er en gratis leksjon i DevOps-bootcamp på CoddyKit. Dette er leksjon 2 av 4. Du kan lese valgfritt 3 leksjoner fra denne læringsstien gratis i sin helhet – deretter låser CoddyKit PRO opp alle leksjoner, samt praktisk øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i DevOps-bootcamp, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i DevOps-bootcamp inneholder totalt 4 leksjoner.

Hvorfor sekvensiell kjøring er treg

Når De kjører kommandoer etter hverandre i et shell-skript, lar De CPU-kjerner stå ubrukt. Tenk på å endre størrelsen på 500 bilder: hvert kall til convert bruker én kjerne, mens de sju andre står ubrukt.

Parallellitet løser dette ved å sende ut flere oppgaver samtidig. To hovedverktøy i Bash gjør dette enkelt:

  • xargs -P — fordeler en liste med inndata på N parallelle arbeiderprosesser
  • Bakgrunnsjobber (&) + wait — oppretter prosesser manuelt og samler dem inn

Denne leksjonen dekker begge fremgangsmåtene, slik at De kan velge riktig verktøy for hver situasjon.

Oppfriskning av grunnleggende xargs

Før De legger til parallellitet, bør De huske hvordan xargs fungerer. Det leser elementer fra stdin og sender dem som argumenter til en kommando.

Flagget -I {} lar Dem plassere inndataelementet hvor som helst i kommandostrengen, ikke bare på slutten.

Eksempelet nedenfor konverterer alle .txt-filer til store bokstaver ved hjelp av tr. Hver fil behandles én om gangen (sekvensiell referanse).

#!/usr/bin/env bash
# Create sample files
mkdir -p /tmp/xargs_demo
for i in 1 2 3; do
  echo "hello world $i" > /tmp/xargs_demo/file$i.txt
done

# Process files one at a time (sequential)
find /tmp/xargs_demo -name '*.txt' | xargs -I {} sh -c 'tr a-z A-Z < "$1"' _ {}

# Cleanup
rm -rf /tmp/xargs_demo

Introduksjon til xargs -P

Legg til flagget -P N i xargs for å kjøre opptil N prosesser parallelt. xargs administrerer arbeiderpoolen automatisk — når en plass blir ledig, starter neste element umiddelbart.

  • -P 0 — opprett like mange prosesser som det finnes inndataelementer (brukes med forsiktighet for store lister)
  • -P 4 — hold maksimalt 4 arbeidere kjørende til enhver tid
  • -n 1 — send nøyaktig ett inndataelement per prosess som startes (et vanlig tilleggsflagg)

Sammen er -n 1 -P 4 det vanligste mønsteret: ett element per arbeider, fire arbeidere samtidig.

#!/usr/bin/env bash
# Simulate 8 tasks, each taking ~1 second
# Sequential would take ~8s; parallel with -P 4 takes ~2s

process_item() {
  local item="$1"
  sleep 1
  echo "Done: $item"
}
export -f process_item

time printf '%s\n' task{1..8} | xargs -n 1 -P 4 bash -c 'process_item "$@"' _

Parallell filbehandling

Et praktisk bruksområde er å komprimere mange loggfiler samtidig. Uten -P blokkerer hvert kall til gzip det neste. Med -P 8 kjører opptil åtte komprimeringer samtidig, slik at alle CPU-kjernene utnyttes.

Legg merke til at -n 1 sikrer at hver parallelle arbeider mottar nøyaktig ett filnavn — noe som er avgjørende når filnavn kan inneholde mellomrom (kombiner med -d '\n' eller -print0 / -0 for sikkerhets skyld).

#!/usr/bin/env bash
# Create dummy log files
mkdir -p /tmp/logs_demo
for i in $(seq 1 12); do
  dd if=/dev/urandom bs=1K count=64 2>/dev/null > /tmp/logs_demo/app_$i.log
done

echo "Files before: $(ls /tmp/logs_demo | wc -l)"

# Compress all .log files in parallel (up to 8 workers)
find /tmp/logs_demo -name '*.log' -print0 \
  | xargs -0 -n 1 -P 8 gzip --fast

echo "Files after : $(ls /tmp/logs_demo | wc -l)"
rm -rf /tmp/logs_demo

Velge riktig -P-verdi

Hvis -P settes for lavt, sløses det med kjerner; hvis det settes for høyt, oppstår det ressurskonkurranse. Et godt utgangspunkt er antallet logiske CPU-kjerner:

  • CPU-bundne oppgaver (komprimering, koding): -P $(nproc)
  • I/O-bundne oppgaver (nettverkskall, diskkjøringer): -P $(($(nproc) * 4)) eller høyere, fordi arbeiderne bruker mesteparten av tiden på å vente
  • Minnebegrensede oppgaver: beregn available_RAM / task_RAM_usage og sett grensen der

nproc returnerer antallet tilgjengelige prosesseringsenheter, og er dermed et portabelt alternativ til hardkodede tall.

#!/usr/bin/env bash
CORES=$(nproc)
IO_WORKERS=$(( CORES * 4 ))

echo "CPU cores   : $CORES"
echo "CPU-bound -P: $CORES"
echo "I/O-bound -P: $IO_WORKERS"

# Example: parallel curl downloads (I/O-bound)
# printf '%s\n' url1 url2 ... | xargs -n 1 -P "$IO_WORKERS" curl -sSO

Bakgrunnsjobber med &

Noen ganger trenger De mer kontroll enn xargs tilbyr — feilhåndtering per jobb, dynamiske lister eller komplekse argumentstrukturer. Bruk skallprogrammenes innebygde bakgrunnsoperator & til å opprette jobber manuelt.

Når & legges til en kommando, får skriptet kontrollen tilbake umiddelbart. Underprosessen kjører i bakgrunnen mens foreldreprosessen fortsetter. Kall wait til slutt for å blokkere til alle underprosessene er ferdige.

#!/usr/bin/env bash
process() {
  local id="$1"
  sleep $(( RANDOM % 3 + 1 ))
  echo "Job $id finished at $(date +%T)"
}

echo "Launching 5 background jobs..."
for id in $(seq 1 5); do
  process "$id" &
done

wait   # Block until every background job completes
echo "All jobs done."

Begrense samtidighet med en jobbpool

Hvis alle jobbene opprettes samtidig med &, kan minnet bli brukt opp når listen er stor. En jobbpool holder maksimalt N jobber kjørende til enhver tid:

  • Etter at hver jobb er opprettet, kontrollerer De hvor mange bakgrunnsjobber som er aktive med jobs -r | wc -l
  • Når antallet når grensen, kaller De wait -n (Bash 4.3+) for å vente på at én valgfri jobb skal bli ferdig før neste opprettes

Dette mønsteret etterligner det xargs -P gjør internt, men gir Dem full fleksibilitet i skriptet rundt hver jobb.

#!/usr/bin/env bash
MAX_JOBS=3

process() {
  local id="$1"
  sleep $(( RANDOM % 3 + 1 ))
  echo "Task $id done"
}

for id in $(seq 1 10); do
  # Throttle: wait for a slot if pool is full
  while (( $(jobs -r | wc -l) >= MAX_JOBS )); do
    wait -n 2>/dev/null || true
  done
  process "$id" &
done

wait
echo "All 10 tasks complete."

Fange opp avslutningskoder fra parallelle jobber

En viktig utfordring med bakgrunnsjobber er at foreldreprosessen ikke automatisk får vite det hvis en underprosess mislykkes. De må fange opp PID-en til hver underprosess og kontrollere avslutningsstatusen med wait <pid>.

Mønsteret nedenfor lagrer alle PID-er i en array og går deretter gjennom arrayen med kall til wait "$pid", som returnerer avslutningskoden til den aktuelle underprosessen.

#!/usr/bin/env bash
set -euo pipefail

task() {
  local id="$1"
  sleep 1
  if (( id == 3 )); then
    echo "Task $id: FAILED" >&2
    return 1
  fi
  echo "Task $id: ok"
}

pids=()
for id in $(seq 1 5); do
  task "$id" &
  pids+=("$!")
done

failed=0
for pid in "${pids[@]}"; do
  if ! wait "$pid"; then
    echo "PID $pid exited with error" >&2
    (( failed++ ))
  fi
done

(( failed == 0 )) && echo "All OK" || { echo "$failed job(s) failed"; exit 1; }

Parallelle nedlastinger med xargs -P

Nettverks-I/O er et typisk tilfelle for høy parallellitet — hver arbeider bruker mesteparten av tiden på å vente på byte. Eksempelet nedenfor henter flere URL-er samtidig og lagrer hver av dem i en fil med et unikt navn.

Viktige flagg:

  • -P 8 — åtte samtidige curl-prosesser
  • -n 1 — én URL per curl-kall
  • --create-dirs -o — curl lagrer i et avledet filnavn
#!/usr/bin/env bash
# Download several small public files in parallel
URLs=(
  "https://httpbin.org/bytes/1024"
  "https://httpbin.org/bytes/2048"
  "https://httpbin.org/bytes/512"
  "https://httpbin.org/bytes/4096"
)

mkdir -p /tmp/parallel_dl

printf '%s\n' "${URLs[@]}" | xargs -n 1 -P 4 bash -c '
  url="$1"
  out="/tmp/parallel_dl/$(echo "$url" | md5sum | cut -c1-8).bin"
  curl -sSf "$url" -o "$out" && echo "Saved $out"
' _

ls -lh /tmp/parallel_dl/
rm -rf /tmp/parallel_dl

Kombinere find, xargs -P og skallfunksjoner

For å bruke en skallfunksjon over flere linjer med xargs må De eksportere den med export -f function_name og deretter starte den via bash -c 'function_name "$@"' _ inne i xargs.

Dette mønsteret gir full skriptfunksjonalitet i hver parallelle arbeider: logging, feilhåndtering og betinget logikk — alt per element.

#!/usr/bin/env bash
mkdir -p /tmp/proc_demo
for i in $(seq 1 8); do echo "data $i" > /tmp/proc_demo/item_$i.txt; done

process_file() {
  local f="$1"
  local base
  base=$(basename "$f" .txt)
  # Simulate work: count words and append a timestamp
  local wc
  wc=$(wc -w < "$f")
  echo "[$base] words=$wc processed=$(date +%T)" >> "/tmp/proc_demo/${base}.result"
}
export -f process_file

find /tmp/proc_demo -name '*.txt' -print0 \
  | xargs -0 -n 1 -P "$(nproc)" bash -c 'process_file "$@"' _

grep '' /tmp/proc_demo/*.result
rm -rf /tmp/proc_demo

Måle hastighetsøkning med time

Mål alltid før De hevder at noe er blitt bedre. Omslutt den parallelle kommandoen med time og sammenlign med den sekvensielle referansen. Den faktiske hastighetsøkningen avhenger av:

  • Uavhengighet mellom oppgavene — oppgavene må ikke dele skrivbar tilstand uten låser
  • Overhead — kostnaden ved å opprette prosesser (omtrent 5–20 ms per prosess) har betydning for små oppgaver
  • Ressurskonkurranse — disk-I/O kan nå kapasitetsgrensen før CPU-en gjør det

Et enkelt referansemønster vises nedenfor — kjør først sekvensielt, deretter parallelt, og sammenlign real-tidene for faktisk medgått tid.

#!/usr/bin/env bash
work() { sleep 0.2; }   # simulate a 200ms task
export -f work

ITEMS=$(seq 1 16)

echo "=== Sequential ==="
time printf '%s\n' $ITEMS | xargs -n 1 bash -c 'work' _

echo
echo "=== Parallel ($(nproc) workers) ==="
time printf '%s\n' $ITEMS | xargs -n 1 -P "$(nproc)" bash -c 'work' _

Kunnskapssjekk: Virkemåten til xargs -P

Test forståelsen Deres av parallell kjøring med xargs -P.

Oppsummering av leksjonen

De har nå to pålitelige teknikker for parallell kjøring i Bash:

  • xargs -n 1 -P N — den enkleste fremgangsmåten; xargs administrerer arbeiderpoolen automatisk. Best når inndataene er en vanlig liste og hvert element tilsvarer én kommando.
  • Bakgrunnsjobber (&) + wait — full kontroll i skriptet; nødvendig når De trenger PID-er per jobb, dynamiske inndata eller detaljert håndtering av avslutningskoder. Bruk wait -n med en teller for å begrense samtidigheten.

Viktige regler å ta med videre:

  • Eksporter skallfunksjoner med export -f før De sender dem gjennom xargs
  • Bruk -print0 / -0 for å håndtere filnavn med mellomrom på en sikker måte
  • Fang opp PID-er i en array og kall wait "$pid" individuelt for å oppdage feil
  • Gjør referansemålinger med time — parallellitet gir bare gevinst når oppgavenes overhead er større enn kostnaden ved å opprette prosesser
  • Bruk -P $(nproc) for CPU-bundne og en høyere faktor for I/O-bundne arbeidsbelastninger
Gratis å komme i gang

Lær deg DevOps-bootcamp med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
142
Leksjoner
568

Ofte stilte spørsmål

Er leksjonen «Parallellitet med xargs -P og bakgrunnsjobber» gratis?

Ja – du kan lese valgfritt 3 av leksjonene i læringsstien DevOps-bootcamp, inkludert «Parallellitet med xargs -P og bakgrunnsjobber», gratis i sin helhet her på nettet. Deretter låser CoddyKit PRO opp alle leksjoner, samt interaktiv øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Kurset i DevOps-bootcamp inneholder totalt 4 leksjoner.

Hva lærer jeg i «Parallellitet med xargs -P og bakgrunnsjobber»?

Kjør uavhengige oppgaver samtidig ved hjelp av parallellmodus i xargs og administrerte puljer med bakgrunnsjobber. Du øver på DevOps-bootcamp med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med DevOps-bootcamp?

Ingen tidligere erfaring er nødvendig. DevOps-bootcamp på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 2 av 4.

Hvor lang tid tar leksjonen «Parallellitet med xargs -P og bakgrunnsjobber»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne DevOps-bootcamp-leksjonen?

Ja. Alle DevOps-bootcamp-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Profilering av skript og unngåelse av unødvendige subshell-er
  2. Parallellitet med xargs -P og bakgrunnsjobber
  3. Orkestrering av arbeidsmengder med GNU parallel
  4. Strømmende pipelines og navngitte pipes for høy gjennomstrømning
← Tilbake til DevOps-bootcamp