Sök…


Syntax

  • fälla action sigspec ... # Kör "action" i en lista över signaler
  • trap sigspec ... # Utelämnande av åtgärder återställer fällor för signaler

parametrar

Parameter Menande
-p Lista för närvarande installerade fällor
-l Lista signalnamn och motsvarande nummer

Anmärkningar

trap är ett speciellt inbyggt skal. Det definieras i POSIX , men bash lägger till några användbara tillägg också.

Exempel som är POSIX-kompatibla börjar med #!/bin/sh , och exempel som börjar med #!/bin/bash använder en bash-förlängning.

Signalerna kan antingen vara ett signalnummer, ett signalnamn (utan SIG-prefixet) eller det speciella nyckelordet EXIT .

De som garanteras av POSIX är:

siffra namn anteckningar
0 UTGÅNG Kör alltid vid skalutgång, oavsett utgångskod
1 SIGHUP
2 SIGINT Det här är vad ^C skickar
3 SIGQUIT
6 SIGABRT
9 SIGKILL
14 SIGALRM
15 SIGTERM Det här är vad kill skickar som standard

Fånga SIGINT eller Ctl + C

Fällan återställs för underskal, så sleep kommer fortfarande att fungera på SIGINT signalen som skickas av ^C (vanligtvis genom att sluta), men överordnadsprocessen (dvs skalskriptet) kommer inte.

#!/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

Och en variant som fortfarande låter dig avsluta huvudprogrammet genom att trycka på ^C två gånger på en sekund:

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

Introduktion: rensa upp tillfälliga filer

Du kan använda trap kommandot för att "fälla" signaler; detta är skalekvivalenten för signal() eller sigaction() kallar C och de flesta andra programmeringsspråk för att fånga signaler.

En av de vanligaste användningarna av trap är att rensa upp tillfälliga filer på både en förväntad och oväntad utgång.

Tyvärr gör inte tillräckligt med skalskript :-(

#!/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.

Samla en lista över fällearbeten för att köra vid utgången.

Har du någonsin glömt att lägga till en trap att rensa upp en tillfällig fil eller göra annat arbete vid utgången?

Har du någonsin satt en fälla som avbröt en annan?

Den här koden gör det enkelt att lägga till saker som ska göras vid avslutande av ett objekt åt gången, snarare än att ha ett stort trap någonstans i din kod, vilket kan vara lätt att glömma.

# 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
}

Döda barnprocesser vid utgång

Fälluttryck behöver inte vara enskilda funktioner eller program, de kan också vara mer komplexa uttryck.

Genom att kombinera jobs -p och kill kan vi döda alla spawnade barnprocesser i skalet vid utgången:

trap 'jobs -p | xargs kill' EXIT

reagera på ändring av terminalfönsterstorlek

Det finns en signal WINCH (WINdowCHange), som avfyras när man ändrar storlek på ett terminalfönster.

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


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow