Parameter Meaning
-p 列出当前安装的陷阱
-l 列出信号名称和相应编号

Section 47.1: 清理临时文件files

你可以使用 trap 命令来“trap”信号;这相当于 C 语言和大多数其他编程语言中用来捕捉信号的 signal() 或 sigaction() 调用。

trap 最常见的用途之一是在预期和意外退出时清理临时文件。

遗憾的是,这样做的 shell 脚本还不够多

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

Section 47.2: 捕捉 SIGINT 或 Ctl+C

子进程的 trap 会被重置,因此睡眠进程仍会对 ^C 发送的 SIGINT 信号采取行动(通常是退出),但父进程(即 shell 脚本)不会。

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

还有一种变体就是在一秒钟内按两次 ^C 键退出主程序:

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

Section 47.3:积累在退出时运行的 “trap”工作列表

你是否曾经忘记添加一个 trap 来清理临时文件或在退出时做其他工作?

你是否设置了一个 trap ,却取消了另一个?

有了这段代码,你就可以很方便地在退出时逐项添加要做的事情,而不必在代码中的某个地方设置一个大的 trap 语句,因为这样很容易忘记。

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

Section 47.4: 在退出时杀死子进程

trap 表达式不一定是单独的函数或程序,也可以是更复杂的表达式。

通过结合 jobs -p 和 kill,我们可以在退出时杀死 shell 产生的所有子进程:

trap 'jobs -p | xargs kill' EXIT

Section 47.5: 终端窗口大小变化时的反应

有一个信号 WINCH ( WINdowCHange),在调整终端窗口大小时触发。

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