Parallelisme med xargs -P og baggrundsjob
Kør uafhængige opgaver samtidigt ved hjælp af xargs' paralleltilstand og administrerede puljer af baggrundsjob.
Parallelisme med xargs -P og baggrundsjob er en gratis Intensiv DevOps-uddannelse-lektion på CoddyKit. Dette er lektion 2 af 4. Du kan læse alle 3 lektioner i dette læringsspor gratis i deres fulde længde — derefter låser CoddyKit PRO alle lektioner op samt praktiske øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Den er en del af læringsforløbet i Intensiv DevOps-uddannelse, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Intensiv DevOps-uddannelse-kurset indeholder 4 lektioner i alt.
Hvorfor sekventiel kørsel er langsom
Når du kører kommandoer efter hinanden i et shell-script, lader du CPU-kerner stå ubenyttede. Forestil dig, at du ændrer størrelsen på 500 billeder: hvert kald til convert bruger én kerne, mens de øvrige syv står ubenyttede.
Parallelitet løser dette ved at sende flere opgaver af sted samtidig. To primære værktøjer i Bash gør dette nemt:
- xargs -P — fordeler en liste med input på N parallelle arbejderprocesser
- Baggrundsjob (&) + wait — opretter processer manuelt og indsamler dem
Denne lektion gennemgår begge fremgangsmåder, så du kan vælge det rigtige værktøj til hver situation.
Genopfriskning af det grundlæggende i xargs
Før du tilføjer parallelitet, skal du genkalde dig, hvordan xargs fungerer. Den læser elementer fra stdin og giver dem som argumenter til en kommando.
Flaget -I {} lader dig placere inputelementet hvor som helst i kommandostrengen, ikke kun til sidst.
Eksemplet nedenfor konverterer hver .txt-fil til store bogstaver ved hjælp af tr. Hver fil behandles én ad gangen (sekventielt udgangspunkt).
#!/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_demoIntroduktion til xargs -P
Tilføj flaget -P N til xargs for at køre op til N processer parallelt. xargs administrerer automatisk puljen af arbejdere — når en plads bliver ledig, starter det næste element med det samme.
-P 0— opret så mange processer, som der er inputelementer (brug det med omtanke ved store lister)-P 4— kør højst 4 arbejdere på samme tid-n 1— send præcis ét inputelement til hver kaldt proces (et almindeligt ledsageflag)
Samlet set er -n 1 -P 4 det mest almindelige mønster: ét element pr. arbejder og fire arbejdere 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 "$@"' _Parallel filbehandling
Et praktisk anvendelsesområde er at komprimere mange logfiler samtidig. Uden -P blokerer hvert kald til gzip det næste. Med -P 8 kører op til otte komprimeringer samtidig, så alle CPU-kerner udnyttes.
Bemærk, hvordan -n 1 sikrer, at hver parallel arbejder modtager præcis ét filnavn — det er afgørende, når filnavne kan indeholde mellemrum (kombinér med -d '\n' eller -print0 / -0 for sikkerheds 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_demoVælg den rigtige værdi for -P
Hvis du sætter -P for lavt, spilder du CPU-kerner; hvis du sætter den for højt, opstår der thrashing. Et godt udgangspunkt er antallet af logiske CPU-kerner:
- CPU-begrænsede opgaver (komprimering, kodning):
-P $(nproc) - I/O-begrænsede opgaver (netværkskald, disklæsninger):
-P $(($(nproc) * 4))eller højere, fordi arbejderne bruger det meste af tiden på at vente - Hukommelsesbegrænsede opgaver: beregn
available_RAM / task_RAM_usage, og sæt grænsen dér
nproc returnerer antallet af tilgængelige behandlingsenheder, hvilket gør den til en flytbar erstatning for hårdkodede tal.
#!/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 -sSOBaggrundsjob med &
Nogle gange har du brug for mere kontrol, end xargs giver — fejlhåndtering pr. job, dynamiske lister eller komplekse argumentstrukturer. Brug shellens indbyggede baggrundsoperator & til at oprette job manuelt.
Når du føjer & til en kommando, får scriptet straks kontrollen tilbage. Det underordnede job kører i baggrunden, mens det overordnede job fortsætter. Kald wait til sidst for at blokere, indtil alle underordnede job er færdige.
#!/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."Begræns parallelitet med en jobpulje
Hvis du opretter alle job på én gang med &, kan du opbruge hukommelsen, når listen er stor. En jobpulje holder højst N job kørende ad gangen:
- Efter hvert job er oprettet, skal du kontrollere, hvor mange baggrundsjob der er aktive, med
jobs -r | wc -l - Hvis antallet når grænsen, skal du kalde
wait -n(Bash 4.3+) for at vente på, at et vilkårligt job bliver færdigt, før du opretter det næste
Dette mønster efterligner det, som xargs -P gør internt, men giver dig fuld fleksibilitet i scriptingen omkring hvert job.
#!/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."Indfang afslutningskoder fra parallelle job
En vigtig udfordring ved baggrundsjob er, at det overordnede script ikke automatisk ved det, hvis en underordnet proces mislykkes. Du skal indfange hvert underordnede jobs PID og kontrollere dets afslutningsstatus med wait <pid>.
Mønsteret nedenfor gemmer alle PID'er i et array og gennemløber derefter arrayet, mens det kalder wait "$pid", som returnerer afslutningskoden for det specifikke underordnede job.
#!/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 downloads med xargs -P
Netværks-I/O er et skoleeksempel på høj parallelitet — hver arbejder bruger det meste af tiden på at vente på bytes. Eksemplet nedenfor henter flere URL'er samtidig og gemmer hver af dem i en fil med et unikt navn.
Vigtige flag:
-P 8— otte samtidige curl-processer-n 1— én URL pr. curl-kald--create-dirs -o— curl gemmer i et afledt 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_dlKombinér find, xargs -P og shell-funktioner
Hvis du vil bruge en shell-funktion over flere linjer med xargs, skal du først eksportere den med export -f function_name og derefter kalde den via bash -c 'function_name "$@"' _ inde i xargs.
Dette mønster giver fuld scripting-funktionalitet i hver parallel arbejder: logning, fejlhåndtering og betinget logik — alt sammen pr. 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_demoMål hastighedsforbedringen med time
Mål altid, før du påstår, at noget er blevet bedre. Omslut din parallelle kommando med time, og sammenlign med det sekventielle udgangspunkt. Den reelle hastighedsforbedring afhænger af:
- Opgavernes uafhængighed — opgaver må ikke dele skrivbar tilstand uden låse
- Overhead — omkostningen ved at oprette processer (~5-20 ms pr. proces) har betydning for små opgaver
- Ressourcekonkurrence — disk-I/O kan nå sin grænse, før CPU'en gør det
Nedenfor vises et simpelt benchmarkmønster — kør først sekventielt, derefter parallelt, og sammenlign de reelle tider i real.
#!/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' _Videnstjek: Sådan fungerer xargs -P
Test din forståelse af parallel kørsel med xargs -P.
Opsummering af lektionen
Du har nu to pålidelige teknikker til parallel kørsel i Bash:
- xargs -n 1 -P N — den enkleste fremgangsmåde; xargs administrerer automatisk jobpuljen. Bedst når dit input er en almindelig liste, og hvert element svarer til én kommando.
- Baggrundsjob (&) + wait — fuld kontrol over scriptingen; nødvendigt, når du har brug for PID'er pr. job, dynamisk input eller detaljeret håndtering af afslutningskoder. Brug
wait -nsammen med en tæller til at begrænse paralleliteten.
Vigtige regler at tage med videre:
- Eksportér shell-funktioner med
export -f, før du sender dem gennemxargs - Brug
-print0/-0til sikker håndtering af filnavne med mellemrum - Gem PID'er i et array, og kald
wait "$pid"individuelt for at opdage fejl - Benchmark med
time— parallelitet giver kun en fordel, når opgavernes overhead overstiger omkostningen ved at oprette processer - Sæt
-P $(nproc)til CPU-begrænsede opgaver, og brug en højere multiplikator til I/O-begrænsede arbejdsbelastninger
Lær Intensiv DevOps-uddannelse med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 142
- Lektioner
- 568
Ofte stillede spørgsmål
Er lektionen “Parallelisme med xargs -P og baggrundsjob” gratis?
Ja — alle 3 lektioner i læringssporet Intensiv DevOps-uddannelse, inklusive “Parallelisme med xargs -P og baggrundsjob”, kan læses gratis i deres fulde længde her på webstedet. Derefter låser CoddyKit PRO alle lektioner op samt interaktive øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Intensiv DevOps-uddannelse-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Parallelisme med xargs -P og baggrundsjob”?
Kør uafhængige opgaver samtidigt ved hjælp af xargs' paralleltilstand og administrerede puljer af baggrundsjob. Du øver dig i Intensiv DevOps-uddannelse med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Intensiv DevOps-uddannelse?
Der kræves ingen tidligere erfaring. Intensiv DevOps-uddannelse på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 2 af 4.
Hvor lang tid tager lektionen “Parallelisme med xargs -P og baggrundsjob”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Intensiv DevOps-uddannelse-lektion?
Ja. Alle Intensiv DevOps-uddannelse-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Profilering af scripts og undgåelse af overflødige subshells
- Parallelisme med xargs -P og baggrundsjob
- Orkestrering af arbejdsbelastninger med GNU parallel
- Streaming-pipelines og navngivne pipes for høj kapacitet