Sikre midlertidige filer og låsem mapper
Brug mktemp og flock til at oprette race-frie midlertidige ressourcer og forhindre samtidige scriptkørsler.
Sikre midlertidige filer og låsem mapper er en gratis Intensiv DevOps-uddannelse-lektion på CoddyKit. Dette er lektion 3 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 midlertidige filer udgør en sikkerhedsrisiko
Bash-scripts har ofte brug for midlertidig lagring — mellemresultater, låsemarkører og klargøringsområder. Men hvis du opretter midlertidige filer uforsigtigt, åbner du for alvorlige sårbarheder.
- Kapløbsbetingelser: En anden proces kan forudsige dit filnavn og oprette filen først, så dine skrivninger omdirigeres.
- Symlink-angreb: En angriber opretter et symlink på den forventede sti, som peger på en følsom fil som
/etc/passwd. - Efterladte filer: Hvis et script går ned, hober midlertidige filer sig op og kan afsløre følsomme data.
De to centrale værktøjer, der eliminerer disse problemer, er mktemp og flock. Denne lektion viser dig, hvordan du bruger begge sikkert og defensivt.
Oprettelse af sikre midlertidige filer med mktemp
mktemp opretter en midlertidig fil med et tilfældigt, uforudsigeligt navn og returnerer dens sti. Den opretter filen atomisk, så ingen anden proces kan tage navnet først.
- Syntaks:
mktemp [TEMPLATE]— skabelonen skal slutte med mindst treX-tegn. - Hvert
Xerstattes af et tilfældigt tegn, hvilket giver et unikt navn som/tmp/script.aB3kQz. - Filen oprettes automatisk med tilladelserne
0600(kan kun læses af ejeren).
Gem altid den returnerede sti i en variabel med det samme, så du senere kan referere til den og rydde den op.
#!/usr/bin/env bash
set -euo pipefail
# Create a secure temp file
TMPFILE=$(mktemp /tmp/myapp.XXXXXX)
echo "Temp file created at: $TMPFILE"
# Write data to it
echo "some intermediate result" > "$TMPFILE"
# Read it back
cat "$TMPFILE"
# Clean up
rm -f "$TMPFILE"Ryd altid op med en trap
Hvis dit script afsluttes uventet — på grund af en fejl, et signal eller fordi set -e udløses — efterlades midlertidige filer, medmindre du registrerer en oprydningshåndterer.
Den indbyggede trap-kommando kører en kommando, når shellen modtager et signal eller afsluttes. Det kanoniske mønster til oprydning af midlertidige filer er:
- Registrér trap'en umiddelbart efter oprettelsen af den midlertidige fil.
- Brug
EXITsom trap, så oprydningen udføres både ved normal og unormal afslutning. - Brug også
INTogTERMsom traps, hvis scriptet kører længe eller er interaktivt.
Det garanterer, at der ikke efterlades forældreløse filer, selv hvis scriptet afsluttes midt under kørslen.
#!/usr/bin/env bash
set -euo pipefail
TMPFILE=$(mktemp /tmp/report.XXXXXX)
# Register cleanup before doing any real work
cleanup() {
rm -f "$TMPFILE"
echo "Cleaned up $TMPFILE" >&2
}
trap cleanup EXIT
# Do work — even if this fails, cleanup() will run
echo "Processing..." > "$TMPFILE"
grep "result" "$TMPFILE" || true
echo "Done. File will be removed on exit."Oprettelse af midlertidige mapper med mktemp -d
Nogle gange har du brug for en hel mappe til midlertidig lagring af flere filer — for eksempel når du opbygger et arkiv eller pakker en tarball ud, før den behandles. Brug mktemp -d til at oprette en sikker midlertidig mappe.
- Mappen oprettes med tilladelserne
0700(kun ejeren har adgang). - Ryd op med
rm -rfi din trap — sørg for kun at fjerne variablen, aldrig en fast kodet sti. - Brug dobbelte anførselstegn, og kontrollér, at variablen ikke er tom, før du kalder
rm -rf, som et ekstra sikkerhedstjek.
#!/usr/bin/env bash
set -euo pipefail
TMPDIR=$(mktemp -d /tmp/extract.XXXXXX)
cleanup() {
# Guard: only rm if variable is set and non-empty
[[ -n "${TMPDIR:-}" ]] && rm -rf "$TMPDIR"
}
trap cleanup EXIT
echo "Working in $TMPDIR"
# Simulate staging files
echo "file one" > "$TMPDIR/part1.txt"
echo "file two" > "$TMPDIR/part2.txt"
ls "$TMPDIR"
echo "All done."Problemet med samtidige scriptkørsler
Cron-job, systemd-timere og manuelt udløste scripts kan nemt starte flere instanser af det samme script samtidigt. Det medfører:
- Dubletbehandling: De samme databaseposter eller filer behandles to gange.
- Beskadiget output: To instanser skriver til den samme outputfil samtidigt.
- Deadlocks eller delvis tilstand: Begge instanser ændrer delte ressourcer i en sammenflettet og uforudsigelig rækkefølge.
Den traditionelle løsning var at skrive en PID-fil og kontrollere den ved opstart — men denne tilgang har et kapløbsvindue mellem kontrollen og skrivningen. Den korrekte moderne løsning er flock, som bruger kernens rådgivende låsemekanisme til at opnå en lås uden kapløbsforhold.
Låsning med flock: Mønsteret på én linje
flock erhverver en rådgivende lås på en fildeskriptor, før en kommando køres. Den enkleste anvendelse omslutter hele dit script fra kommandolinjen:
flock -n /var/lock/myscript.lock bash myscript.sh
-n(ikke-blokerende): afslutter straks med status 1, hvis låsen allerede er taget, i stedet for at vente.- Uden
-nblokererflock, indtil låsen bliver ledig — nyttigt til kødannelse. - Selve låsefilen er blot en markør; dens indhold er ligegyldigt. Det er sikkert at lade den blive mellem kørsler.
- Når processen, der har låsen, afsluttes, frigiver kernen den automatisk — manuel oprydning er ikke nødvendig.
#!/usr/bin/env bash
# launcher.sh — prevents concurrent runs of worker.sh
set -euo pipefail
LOCKFILE="/tmp/myworker.lock"
if ! flock -n "$LOCKFILE" bash -c 'echo "Running worker..."; sleep 2; echo "Done."'; then
echo "Another instance is already running. Exiting." >&2
exit 1
fiflock i et script ved hjælp af en fildeskriptor
Hvis du vil låse inde i et script i stedet for at omslutte det udefra, skal du bruge exec til at åbne en fildeskriptor og derefter kalde flock på den. Dette er det idiomatiske mønster, der bruges i produktionsscripts.
exec 200>"$LOCKFILE"åbner filen på deskriptor 200 til skrivning (og opretter den om nødvendigt).flock -n 200forsøger at låse deskriptor 200 uden at blokere.- Fordi låsen er knyttet til fildeskriptoren (ikke filnavnet), frigives den automatisk, når shell-processen afsluttes.
- Deskriptornumrene 200-299 bruges traditionelt for at undgå sammenstød med stdin/stdout/stderr.
#!/usr/bin/env bash
set -euo pipefail
LOCKFILE="/tmp/myjob.lock"
# Open lock file on FD 200
exec 200>"$LOCKFILE"
# Attempt non-blocking lock
if ! flock -n 200; then
echo "ERROR: Another instance of this script is running." >&2
exit 1
fi
echo "Lock acquired. Starting work..."
sleep 1
echo "Work complete. Lock will be released on exit."Kombination af mktemp og flock i ét script
Rigtigt defensive scripts har brug for begge dele: en lås, der forhindrer samtidige kørsler, og sikre midlertidige filer til mellemdata. Her er det komplette mønster, der kombinerer begge teknikker:
- Erhverv låsen først — før du opretter midlertidige filer — så kun én instans overhovedet udfører arbejde.
- Opret midlertidige ressourcer, efter at låsen er bekræftet.
- Registrer
trapumiddelbart efter oprettelsen af de midlertidige ressourcer, så oprydning er garanteret, uanset hvordan scriptet afsluttes. - Låsefilen må aldrig ligge i den midlertidige mappe — den skal bevares mellem kørsler, så
flockkan referere til den.
#!/usr/bin/env bash
set -euo pipefail
LOCKFILE="/tmp/report_builder.lock"
exec 200>"$LOCKFILE"
if ! flock -n 200; then
echo "Already running — aborting." >&2
exit 1
fi
# Now safe to create temp resources
TMPDIR=$(mktemp -d /tmp/report.XXXXXX)
TMPLOG=$(mktemp /tmp/report_log.XXXXXX)
cleanup() {
rm -rf "${TMPDIR:-}"
rm -f "${TMPLOG:-}"
}
trap cleanup EXIT
echo "Building report in $TMPDIR" | tee "$TMPLOG"
echo "Step 1 complete" >> "$TMPLOG"
cat "$TMPLOG"Låsem mapper som alternativ låsemekanisme
På systemer, hvor flock ikke er tilgængelig (nogle indlejrede systemer eller netværksfilsystemer som NFS), kan du i stedet bruge låsem mapper. mkdir er atomisk på POSIX-systemer: det lykkes kun, hvis mappen ikke allerede findes.
- Opret låsemappen med
mkdir /tmp/myscript.lock.d— hvis en anden instans allerede har oprettet den, mislykkesmkdirstraks. - Gem metadata (for eksempel PID'en) i mappen til diagnosticering.
- Fjern altid mappen i en
trapvedEXIT. - Forbehold: I modsætning til
flockfrigives en mappelås IKKE automatisk, hvis processen dræbes med-9, eller hvis maskinen genstarter — tilføj et tjek, der opdager forældede låse.
#!/usr/bin/env bash
set -euo pipefail
LOCKDIR="/tmp/myscript.lock.d"
# Atomic mkdir — fails if directory already exists
if ! mkdir "$LOCKDIR" 2>/dev/null; then
# Check if the holding PID is still alive
HOLDER_PID=$(cat "$LOCKDIR/pid" 2>/dev/null || echo "")
if [[ -n "$HOLDER_PID" ]] && kill -0 "$HOLDER_PID" 2>/dev/null; then
echo "Locked by PID $HOLDER_PID. Exiting." >&2
exit 1
else
echo "Stale lock detected. Removing and continuing." >&2
rm -rf "$LOCKDIR"
mkdir "$LOCKDIR"
fi
fi
echo "$$" > "$LOCKDIR/pid"
trap 'rm -rf "$LOCKDIR"' EXIT
echo "Lock acquired via directory. Running..."
sleep 1
echo "Done."Ventning med timeout ved hjælp af flock
Nogle gange vil du vente på en lås i stedet for at fejle med det samme — men du vil ikke vente for evigt. flock understøtter en timeout med flaget -w.
flock -w 10 200venter i op til 10 sekunder på låsen og afslutter derefter med status 1, hvis den stadig ikke er tilgængelig.- Dette er ideelt til scripts, der skal sættes i kø efter en kortvarig forgænger, men give op, hvis forgængeren sidder fast.
- Kombiner
-wmed en meningsfuld fejlmeddelelse, der indeholder kontekst — låsefilens sti og hvor længe du ventede — så operatører hurtigt kan diagnosticere hængende processer.
#!/usr/bin/env bash
set -euo pipefail
LOCKFILE="/tmp/data_sync.lock"
TIMEOUT=15
exec 200>"$LOCKFILE"
echo "Waiting up to ${TIMEOUT}s for lock on $LOCKFILE..."
if ! flock -w "$TIMEOUT" 200; then
echo "ERROR: Could not acquire lock after ${TIMEOUT}s." \
"Another instance may be hung." >&2
exit 1
fi
echo "Lock acquired. Syncing data..."
sleep 1
echo "Sync complete."Defensiv tjekliste: sikre midlertidige ressourcer
Gå denne tjekliste igennem, før du leverer et script, der bruger midlertidige filer eller låsning:
- Brug
mktemp, aldrig faste stier —/tmp/myapp.tmper forudsigelig og kan udnyttes. - Gem stien med det samme —
TMPFILE=$(mktemp ...)før enhver anden kommando. - Registrer
trap cleanup EXITumiddelbart efter oprettelsen — ikke i slutningen af scriptet. - Sæt dobbelte anførselstegn omkring alle variabelreferencer —
rm -f "$TMPFILE", aldrigrm -f $TMPFILE. - Foretræk
flockfrem for PID-filer — kernestyret og automatisk frigivet ved nedbrud. - Brug ikke-blokerende
-nsom standard — lydløst blokerende låse skjuler ydelsesproblemer. - Placér låsefilen uden for den midlertidige mappe — så den overlever oprydningstrappen.
- Test oprydningsadfærden — kør dit script, og brug
kill -9på det midt under kørslen; kontrollér, at der ikke er nogen resterende filer (for scripts baseret påflock; mappelåse kræver ekstra omtanke).
Videnstjek: Adfærd for flock-flag
Et cron-job kører hvert minut og behandler en delt fil. Du ønsker, at enhver ny kørsel afslutter straks med en fejl, hvis en tidligere kørsel stadig er aktiv, uden at vente. Hvilken flock-kaldemåde implementerer dette korrekt?
Opsummering: sikre midlertidige filer og låsem mapper
I denne lektion lærte du de to vigtigste værktøjer til defensiv ressourcestyring i Bash:
mktempopretter uforudsigelige midlertidige filer (0600) og mapper (0700) med sikre tilladelser og eliminerer kapløbsforhold og symlink-angreb, som plager faste stier.trap cleanup EXITgaranterer, at midlertidige filer fjernes ved enhver afslutning — normal, udløst af en fejl eller udløst af et signal — når den registreres umiddelbart efter oprettelsen.flockgiver kernehåndhævet rådgivende låsning: brug-ntil at fejle hurtigt ved konkurrence om låsen,-w Ntil at vente med en timeout og mønsteretexec 200>filetil låsning inde i et script, hvor kernen automatisk frigiver låsen, når processen afsluttes.- Låsem mapper (
mkdir) er et portabelt alternativ i miljøer, hvorflockikke er tilgængelig, men kræver udtrykkelig registrering af forældede låse. - Hold altid låsefilen uden for den midlertidige mappe, og sæt dobbelte anførselstegn omkring alle variabler, der bruges i oprydningen.
Ved at kombinere mktemp + flock + trap får du scripts, der er sikre mod samtidige kørsler, uforudsigelige nedbrud og ondsindet manipulation af filsystemet.
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 “Sikre midlertidige filer og låsem mapper” gratis?
Ja — alle 3 lektioner i læringssporet Intensiv DevOps-uddannelse, inklusive “Sikre midlertidige filer og låsem mapper”, 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 “Sikre midlertidige filer og låsem mapper”?
Brug mktemp og flock til at oprette race-frie midlertidige ressourcer og forhindre samtidige scriptkørsler. 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 3 af 4.
Hvor lang tid tager lektionen “Sikre midlertidige filer og låsem mapper”?
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
- Streng tilstand med set -euo pipefail
- Trap-håndteringer til oprydning og signaler
- Sikre midlertidige filer og låsem mapper
- Idempotente scripts og retry-logik med backoff