Surfend op het nationale netwerk kwam ik een interessant artikel (die ik hier tekstueel breng omdat het meesterlijk wordt uitgelegd) waar de auteur ons laat zien hoe we onze Bash-scripts robuuster kunnen maken met Vallen.
Maak uw bash-scripts robuuster met traps
Stel je voor dat je een bash-script hebt dat elke zes uur elke dag wordt uitgevoerd en dat het op een gegeven moment mislukt of dat hetzelfde script twee keer tegelijk wordt uitgevoerd. Deze twee situaties zijn nogal ongemakkelijk omdat ze menselijke tussenkomst vereisen om te worden gecorrigeerd of op bepaalde momenten kunnen ze niet worden aangepakt, waardoor het systeem in een inconsistente staat verkeert. De oplossing hiervoor is onder meer het gebruik van vallen.
Traps is een eenvoudige en effectieve manier om de uitvoer van bash-scripts te beheren. Laten we teruggaan naar dezelfde beginsituatie, als het script handmatig wordt gestopt, bijvoorbeeld met ctrl-c, wordt het onderbroken en wordt het uitgangssignaal geretourneerd
INT
en als het eindigt met
kill
dan zou de output zijn
TERM
.
Met alle mogelijke exitcodes kunnen worden bekeken
kill -l
echter de meest gebruikte zijn precies
INT, TERMIJN, VERLATEN
Als het script bijvoorbeeld bestaat uit het synchroniseren van bestanden met
rsync
het meest verstandige is om te vertrouwen op een vergrendelingsbestand waardoor het script niet tegelijkertijd kan worden uitgevoerd:
LOCK = "/ var / run / rsync.lock" als [! -e $ LOCK]; raak vervolgens $ LOCK rsync -avz foo bar rm $ LOCK anders echo "rsync draait al" fi
In gewoon Spaans controleert het bovenstaande script of het vergrendelingsbestand bestaat en als het niet bestaat, wordt het aangemaakt en vervolgens de bijbehorende opdracht uitgevoerd, waarbij uiteindelijk het vergrendelingsbestand wordt verwijderd. Als het bestand bestaat, stuurt het script gewoon een bericht naar de gebruiker om aan te geven dat de opdracht al wordt uitgevoerd.
Als er zich echter een problematische situatie voordoet, kan het gebeuren dat het vergrendelingsbestand niet wordt geëlimineerd, waardoor ongewenste effecten worden verpest. De oplossing is heel simpel:
LOCK = "/ var / run / rsync.lock" als [! -e $ LOCK]; dan trap "rm -f $ LOCK; exit" INT TERM EXIT touch $ LOCK rsync -avz foo bar rm $ LOCK trap - INT TERM EXIT anders echo "rsync draait al" fi
Het bijzondere van deze oplossing is dat het commando is ingesloten in een val, zodat wanneer er een signaal wordt ontvangen
INT, TERMIJN, VERLATEN
het script stopt en wist het vergrendelingsbestand.
Het is de moeite waard om te zeggen dat er een wedstrijdsituatie in het bovenstaande script kan zijn tussen het moment dat het vergrendelingsbestand wordt geverifieerd en het moment dat het wordt gemaakt. Een mogelijke oplossing zou zijn om een redirect en bash's noclobber-modus te gebruiken die niet omleidt naar een bestaand bestand:
LOCK = "/ var / run / rsync.lock" if (set -o noclobber; echo $$> "$ LOCK") 2> / dev / null; val dan 'rm -f "$ LOCK" in; exit $? ' INT TERM EXIT rsync -avz foo bar rm -f $ LOCK trap - INT TERM EXIT anders echo "rsync draait al: $ (cat $ LCK)" fi
Het bijzondere van dit laatste is dat het wordt gebruikt zoals ik al zei, de noclobber-modus en dat het vergrendelingsbestand de PID bevat van het proces dat wordt uitgevoerd.
Het is ook vermeldenswaard dat er andere oplossingen zijn, zoals
flock
o
solo
in dit bericht wilde ik de oplossingen echter delen met de eigen middelen van bash. Hiermee kun je iets meer over Traps leren uitstekende gids.
Briljant! Bedankt voor het delen.
Leuk artikel, verander gewoon 'echo' rsync is al actief: $ (cat $ LCK) '' naar 'echo' rsync is al actief: $ (cat $ LOCK) "'
groeten
Een heel interessant artikel, ja meneer! Dit bewaar ik.
Het is een erg handig commando om in gedachten te houden. Ik heb het gebruikt in een script dat ik in een bericht heb gepubliceerd om enkele bestanden te verwijderen die het script heeft gemaakt toen het werd gestopt.
Heel interessant, ja meneer.