Bash
"Trap" gebruiken om te reageren op signalen en systeemgebeurtenissen
Zoeken…
Syntaxis
- trap action sigspec ... # Voer "action" uit op een lijst met signalen
- trap sigspec ... # Als actie wordt weggelaten, worden vallen voor signalen opnieuw ingesteld
parameters
Parameter | Betekenis |
---|---|
-p | Lijst met momenteel geïnstalleerde vallen |
l | Lijst met signaalnamen en bijbehorende nummers |
Opmerkingen
Het trap
is een speciale ingebouwde shell. Het is gedefinieerd in POSIX , maar bash voegt ook enkele nuttige extensies toe.
Voorbeelden die POSIX-compatibel zijn, beginnen met #!/bin/sh
en voorbeelden die beginnen met #!/bin/bash
gebruiken een bash-extensie.
De signalen kunnen een signaalnummer, een signaalnaam (zonder het SIG-voorvoegsel) of het speciale trefwoord EXIT
.
Die gegarandeerd door POSIX zijn:
Aantal | Naam | Notes |
---|---|---|
0 | UITGANG | Voer altijd shell-exit uit, ongeacht de exit-code |
1 | SIGHUP | |
2 | SIGINT | Dit is wat ... ^C stuurt |
3 | SIGQUIT | |
6 | SIGABRT | |
9 | SIGKILL | |
14 | SIGALRM | |
15 | SIGTERM | Dit is wat kill standaard verzendt |
SIGINT of Ctl + C vangen
De val wordt opnieuw ingesteld voor subshells, dus de sleep
zal nog steeds werken op het SIGINT
signaal verzonden door ^C
(meestal door te stoppen), maar het bovenliggende proces (dwz het shellscript) niet.
#!/bin/sh
# Run a command on signal 2 (SIGINT, which is what ^C sends)
sigint() {
echo "Killed subshell!"
}
trap sigint INT
# Or use the no-op command for no output
#trap : INT
# This will be killed on the first ^C
echo "Sleeping..."
sleep 500
echo "Sleeping..."
sleep 500
En een variant waarmee u nog steeds het hoofdprogramma kunt afsluiten door tweemaal in een seconde op ^C
drukken:
last=0
allow_quit() {
[ $(date +%s) -lt $(( $last + 1 )) ] && exit
echo "Press ^C twice in a row to quit"
last=$(date +%s)
}
trap allow_quit INT
Inleiding: tijdelijke bestanden opschonen
U kunt het trap
commando gebruiken om signalen te "vangen"; dit is het shell-equivalent van de sigaction()
van signal()
of sigaction()
in C en de meeste andere programmeertalen om signalen op te vangen.
Een van de meest voorkomende toepassingen van trap
is het opschonen van tijdelijke bestanden bij zowel een verwachte als een onverwachte exit.
Helaas doen dit niet genoeg shell-scripts :-(
#!/bin/sh
# Make a cleanup function
cleanup() {
rm --force -- "${tmp}"
}
# Trap the special "EXIT" group, which is always run when the shell exits.
trap cleanup EXIT
# Create a temporary file
tmp="$(mktemp -p /tmp tmpfileXXXXXXX)"
echo "Hello, world!" >> "${tmp}"
# No rm -f "$tmp" needed. The advantage of using EXIT is that it still works
# even if there was an error or if you used exit.
Verzamel een lijst met trapwerkzaamheden die bij uitgang moeten worden uitgevoerd.
Ben je ooit vergeten een trap
toe te voegen om een tijdelijk bestand op te schonen of ander werk te doen bij het afsluiten?
Heb je ooit een val gezet die een andere heeft geannuleerd?
Deze code maakt het gemakkelijk om dingen toe te voegen die moeten worden gedaan bij het afsluiten van één item tegelijk, in plaats van ergens een grote trap
instructie in uw code te hebben, die misschien gemakkelijk te vergeten is.
# on_exit and add_on_exit
# Usage:
# add_on_exit rm -f /tmp/foo
# add_on_exit echo "I am exiting"
# tempfile=$(mktemp)
# add_on_exit rm -f "$tempfile"
# Based on http://www.linuxjournal.com/content/use-bash-trap-statement-cleanup-temporary-files
function on_exit()
{
for i in "${on_exit_items[@]}"
do
eval $i
done
}
function add_on_exit()
{
local n=${#on_exit_items[*]}
on_exit_items[$n]="$*"
if [[ $n -eq 0 ]]; then
trap on_exit EXIT
fi
}
Het doden van kindprocessen bij afsluiten
Trap-expressies hoeven geen afzonderlijke functies of programma's te zijn, het kunnen ook complexere expressies zijn.
Door jobs -p
en kill
combineren, kunnen we alle spawned onderliggende processen van de shell bij het afsluiten doden:
trap 'jobs -p | xargs kill' EXIT
reageren op verandering van de grootte van het terminalvenster
Er is een signaal WINCH (WINdowCHange), dat wordt geactiveerd wanneer het formaat van een terminalvenster wordt gewijzigd.
declare -x rows cols
update_size(){
rows=$(tput lines) # get actual lines of term
cols=$(tput cols) # get actual columns of term
echo DEBUG terminal window has no $rows lines and is $cols characters wide
}
trap update_size WINCH