När en schemalagd säkerhetskopia misslyckas mitt i natten vill du snabbt veta om felet kom från databasen, komprimeringen eller överföringen. Ett Bash-skript passar ofta bra för att koppla ihop sådana verktyg, men bara om fel och indata hanteras med eftertanke.

Ett bra Bash-skript gör serverjobb repeterbara och fel synliga
- Använd Bash när uppgiften främst kopplar ihop befintliga kommandoradsverktyg.
- Citera variabler så att mellanslag och specialtecken i sökvägar inte ändrar kommandot.
- Kontrollera fel uttryckligen;
set -efångar inte alla fel på ett intuitivt sätt. - Kör ShellCheck före driftsättning och testa även det felaktiga scenariot.
Bash passar bäst när skriptet binder ihop befintliga verktyg
En Bash-fil är som en liten arbetsledare för kommandon som redan finns på systemet: den kan kontrollera en katalog, starta en säkerhetskopia och skriva resultatet till en logg. För ett avgränsat jobb på en Linux-server blir lösningen ofta lätt att läsa och köra, särskilt när det mesta arbetet redan görs av exempelvis tar, rsync eller systemctl.
Gränsen kommer när logiken växer. Behöver skriptet hantera många datatyper, komplicerade API-anrop eller omfattande felåterhämtning tycker jag att Python ofta blir tydligare. Bash är starkt som lim mellan program, men skört som ersättning för ett större program.
En säkerhetskopia bör stoppa innan den rapporteras som klar
Det farliga felet är inte alltid att ett kommando kraschar. En pipeline kan ge ett missvisande resultat om ett tidigt kommando misslyckas men det sista ändå avslutas utan fel. GNU:s Bash Reference Manual beskriver hur pipefail ändrar pipeline-statusen så att ett fel i ett tidigare led kan synas.
Här är en kompakt grund för en säkerhetskopia. Den kräver att målkatalogen redan finns och lämnar ett tydligt felmeddelande om något kommando i pipelinen misslyckas:
#!/usr/bin/env bash
set -o pipefail
source_dir="/srv/site"
backup_dir="/var/backups/site"
archive="$backup_dir/site-$(date +%F).tar.gz"
if [[ ! -d "$source_dir" || ! -d "$backup_dir" ]]; then
printf 'Käll- eller målkatalog saknas\n' >&2
exit 1
fi
if tar -czf - -C "$source_dir" . | tee "$archive" >/dev/null; then
printf 'Säkerhetskopia skapad: %s\n' "$archive"
else
status=$?
rm -f -- "$archive"
printf 'Säkerhetskopian misslyckades, status %s\n' "$status" >&2
exit "$status"
fipipefail är valt här i stället för att blint lägga till set -e. Manualen påpekar att -e har undantag, bland annat i villkor och vissa listor av kommandon. Kontrollera därför kritiska steg där resultatet används, i stället för att anta att en enda inställning löser all felhantering.
Citat runt variabler hindrar sökvägar från att splittras
En katalog som heter /srv/site files räcker för att avslöja ett vanligt Bash-fel. Om en variabel används utan citattecken kan skalet dela upp värdet vid blanksteg och även tolka jokertecken; skriv därför normalt "$source_dir", inte $source_dir.
Föredra också [[ ... ]] för Bash-villkor och $(kommando) för kommandosubstitution. Googles Shell Style Guide rekommenderar bland annat dessa mönster och lyfter ShellCheck som ett sätt att hitta vanliga misstag.
| Situation | Trolig följd | Gör så här |
|---|---|---|
| Sökväg eller argument kan innehålla blanksteg | Oquotad variabel delas upp i flera argument | Citat variabeln, till exempel "$archive" |
| Ett tidigt steg i en pipeline fallerar | Utan pipefail kan det sista stegets status dölja felet | Använd set -o pipefail och hantera felgrenen |
Skriptet körs med sh script.sh | Bash-specifika konstruktioner kan bete sig fel | Kör med Bash, exempelvis bash script.sh, eller gör skriptet POSIX-kompatibelt |
| ShellCheck visar en varning | Det kan röra sig om ett verkligt quoting- eller logikfel | Läs varningen och rätta orsaken innan eventuellt undantag |
ShellCheck hittar fel innan skriptet når servern
En skriptfil kan se rimlig ut och ändå hantera ett argument fel. ShellCheck analyserar Bash- och shellkod statiskt och flaggar bland annat risker med oquotade variabler. Jag tycker att det är en av de mest användbara kvalitetskontrollerna för ett skript som ska köras automatiskt, eftersom en liten miss i ett cron-jobb annars kan ligga oupptäckt länge.
Kör kontrollen lokalt med shellcheck backup.sh och syntaxkontrollera sedan med bash -n backup.sh. Det senare kör inte själva arbetsflödet, så testa också med en saknad källkatalog och kontrollera att skriptet avslutas med felstatus i stället för att skriva ut ett lyckat meddelande.
Om skriptet ligger i Git kan samma kontroller köras i CI innan ändringen godkänns. Då upptäcks ett trasigt skript före driftsättning, medan ett test med tillfälliga kataloger kan bekräfta att det producerade arkivet faktiskt går att läsa.
Välj Bash för korta arbetsflöden, ett annat språk för växande logik
Ett Bash-skript lämpar sig när stegen är få, kommandona är etablerade och resultatet går att kontrollera med exitstatus och filer. Om du börjar bygga avancerad argumenttolkning, återförsök, JSON-hantering och flera beroende funktioner blir skriptet snabbt svårare att felsöka än ett litet program i ett språk med tydligare datastrukturer.
En användbar tumregel är att behålla Bash när det mest handlar om att starta och koppla ihop systemverktyg. Om själva beslutslogiken börjar dominera skulle jag flytta den till Python och låta Bash, om det behövs, bara starta programmet.
Gör resultatet synligt innan jobbet körs obevakat
Automatisering är först trygg när misslyckanden också märks. Skriv fel till standard error, ge processen en meningsfull exitstatus och låt schemaläggaren eller övervakningen reagera på den; ett tyst fel är lätt att förväxla med en lyckad körning.
För säkerhetskopian betyder det att kontrollera både skriptets status och att arkivet går att läsa. Ett kort Bash-skript kan spara återkommande arbete, men den lilla kontrollen efter körningen är det som skiljer automation från enbart automatiserad optimism.