När jag bläddrade i det nationella nätverket stötte jag på en intressant artikel (som jag tar här ordagrant eftersom det är mästerligt förklarat) där författaren visar oss hur vi gör våra Bash-skript mer robusta med Fällor.
Gör dina bash-skript mer robusta med fällor
Föreställ dig att du har ett bash-skript som körs var sjätte timme varje dag och någon gång misslyckas eller att samma skript körs två gånger samtidigt. Dessa två situationer är ganska obekväma eftersom de kräver mänskligt ingripande för att korrigeras eller vid vissa tillfällen inte kan hanteras, vilket lämnar systemet i ett inkonsekvent tillstånd. Lösningen på bland annat detta är att använda fällor.
Traps är ett enkelt och effektivt sätt att kontrollera produktionen av bash-skript. Låt oss gå tillbaka till samma initiala situation, om skriptet stoppas manuellt, till exempel med ctrl-c, avbryts det och returnerar utgångssignalen
INT
och om det slutar med
kill
då skulle utgången bli
TERM
.
Alla möjliga utgångskoder kan ses med
kill -l
men de mest använda är exakt
INT, TERM, EXIT
Om skriptet består till exempel i att synkronisera filer med
rsync
det mest förnuftiga att göra är att lita på en låsfil som inte tillåter att skriptet körs samtidigt:
LOCK="/var/run/rsync.lock" om [ ! -e $LOCK ]; tryck sedan på $LOCK rsync -avz foo bar rm $LOCK annars eko "rsync körs redan" fi
På vanlig spanska kontrollerar det tidigare skriptet om låsfilen finns och om den inte gör det skapar den den och utför sedan motsvarande kommando, slutligen tar den bort låsfilen. Om filen finns skickar skriptet helt enkelt ett meddelande till användaren som indikerar att kommandot redan körs.
Men när det finns en problematisk situation kan det hända att låsfilen inte raderas, vilket förstör oönskade effekter. Lösningen är väldigt enkel:
LOCK="/var/run/rsync.lock" om [ ! -e $LOCK ]; sedan trap "rm -f $LOCK; exit" INT TERM EXIT tryck på $LOCK rsync -avz foo bar rm $LOCK trap - INT TERM EXIT annars eko "rsync körs redan" fi
Det speciella med denna lösning är att kommandot är inneslutet i en fälla, så att när en signal tas emot
INT, TERM, EXIT
skriptet stoppar och tar bort låsfilen.
Det är värt att säga att det kan finnas en konkurrenssituation i ovanstående script mellan det att låsfilen kontrolleras och den tidpunkt då den skapas. En möjlig lösning skulle vara att använda en omdirigering och bashs noclobber-läge som inte omdirigerar till en befintlig fil:
LOCK="/var/run/rsync.lock" if (set -o noclobber; echo $$ > "$LOCK") 2> /dev/null; trap sedan 'rm -f "$LOCK"; avsluta $?' INT TERM EXIT rsync -avz foo bar rm -f $LOCK trap - INT TERM EXIT annars eko "rsync körs redan: $(cat $LCK)" fi
Det speciella med det senare är att det används, som jag redan sa, noclobber-läget och att låsfilen innehåller PID för den process som körs.
Det är också värt att nämna att det finns andra lösningar som
flock
o
solo
men i det här inlägget ville jag dela lösningarna med bashs egna resurser. Du kan lära dig lite mer om Traps med detta utmärkt guide.
Lysande! Tack för att du delar med dig.
Bra artikel, ändra bara 'echo "rsync körs redan: $(cat $LCK)"' till 'echo "rsync körs redan: $(cat $LOCK)"'
hälsningar
En mycket intressant artikel, ja herre! Jag behåller den här.
Detta är ett mycket användbart kommando att vara medveten om. Jag använde det i ett skript som jag publicerade i ett inlägg, för att radera några filer som skriptet skapade när det stoppades.
Mycket intressant, ja sir.