标签: trap

“trap ... INT TERM EXIT”真的有必要吗?

对于许多例子trap使用trap ... INT TERM EXIT的清理任务。但是真的有必要列出所有三个 sigspecs 吗?

手册上说

如果 SIGNAL_SPEC 为 EXIT (0),则在退出 shell 时执行 ARG。

我相信这适用于脚本是否正常完成或因为它收到SIGINTSIGTERM. 一个实验也证实了我的信念:

$ cat ./trap-exit
#!/bin/bash
trap 'echo TRAP' EXIT
sleep 3
$ ./trap-exit & sleep 1; kill -INT %1
[1] 759
TRAP
[1]+  Interrupt               ./trap-exit
$ ./trap-exit & sleep 1; kill -TERM %1
[1] 773
TRAP
[1]+  Terminated              ./trap-exit
Run Code Online (Sandbox Code Playgroud)

那为什么这么多例子一一列举INT TERM EXIT呢?或者我错过了什么,有没有鞋底EXIT会错过的情况?

shell bash signals trap

80
推荐指数
4
解决办法
7万
查看次数

67
推荐指数
5
解决办法
24万
查看次数

陷阱、ERR 和回显错误行

我正在尝试使用 Trap 创建一些错误报告来调用所有错误的函数:

Trap "_func" ERR
Run Code Online (Sandbox Code Playgroud)

是否有可能获得 ERR 信号是从哪条线路发送的?外壳是 bash。

如果我这样做,我可以阅读和报告使用了什么命令并记录/执行一些操作。

或者也许我在这一切都错了?

我测试了以下内容:

#!/bin/bash
trap "ECHO $LINENO" ERR

echo hello | grep "asdf"
Run Code Online (Sandbox Code Playgroud)

并且$LINENO正在返回 2. 不工作。

bash shell-script trap error-handling

40
推荐指数
5
解决办法
7万
查看次数

使用 `set -eu` 时 EXIT 和 ERR 陷阱的正确行为

在使用set -e( errexit), set -u( nounset) 以及 ERR 和 EXIT 陷阱时,我观察到一些奇怪的行为。它们似乎相关,因此将它们放在一个问题中似乎是合理的。

1)set -u不触发 ERR 陷阱

  • 代码:

    #!/bin/bash
    trap 'echo "ERR (rc: $?)"' ERR
    set -u
    echo ${UNSET_VAR}
    
    Run Code Online (Sandbox Code Playgroud)
  • 预期:ERR 陷阱被调用,RC != 0
  • 实际:没有调用ERR 陷阱,RC == 1
  • 注意:set -e不会改变结果

2)set -eu在 EXIT 陷阱中使用退出代码是 0 而不是 1

  • 代码:

    #!/bin/bash
    trap 'echo "EXIT (rc: $?)"' EXIT
    set -eu
    echo ${UNSET_VAR}
    
    Run Code Online (Sandbox Code Playgroud)
  • 预期:退出陷阱被调用,RC == 1
  • 实际:调用退出陷阱,RC == 0
  • 注意:当使用 时set …

scripting bash parameter shell-script trap

31
推荐指数
2
解决办法
2万
查看次数

捕获 SIGINT 等时保留退出代码?

如果我使用trap如在http://linuxcommand.org/wss0160.php#trap上描述的那样在退出之前捕获 ctrl-c(或类似的)和清理,那么我正在更改返回的退出代码。

现在这可能不会在现实世界中产生影响(例如,因为退出代码不可移植,而且在进程终止时的默认退出代码中讨论的那样并不总是明确的)但我仍然想知道是否有真的没有办法阻止这种情况并返回中断脚本的默认错误代码吗?

示例(在 bash 中,但不应将我的问题视为特定于 bash 的问题):

#!/bin/bash
trap 'echo EXIT;' EXIT
read -p 'If you ctrl-c me now my return code will be the default for SIGTERM. ' _
trap 'echo SIGINT; exit 1;' INT
read -p 'If you ctrl-c me now my return code will be 1. ' _
Run Code Online (Sandbox Code Playgroud)

输出:

$ ./test.sh # doing ctrl-c for 1st read
If you ctrl-c me now my return code will be the …
Run Code Online (Sandbox Code Playgroud)

shell signals shell-script exit trap

18
推荐指数
4
解决办法
2万
查看次数

陷阱是由子shell继承的吗?

我尝试了以下脚本:

#!/bin/bash
trap 'echo "touching a file" && touch $FILE' EXIT

foo1(){
        echo "foo1"
}
foo(){
        echo "foo"
        export FILE=${FILE:-/tmp/file1}
}
(foo1)
foo
Run Code Online (Sandbox Code Playgroud)

上述脚本的输出是:

[root@usr1 my_tests]# ./test.sh
foo1
foo
touching a file
Run Code Online (Sandbox Code Playgroud)

但是,我希望在退出时foo1也调用 trap ,这在子shell中调用。

  • 这是预期的吗?
  • 是否trap由子shell继承?
  • 如果是,那么在什么情况下trap由子shell继承?

shell trap subshell

17
推荐指数
3
解决办法
3871
查看次数

等待 bash-builtin 以 100% 的速度消耗 CPU

至少在GNU bash 版本 4.3.42 x86_64 && GNU bash 版本 4.3.11 x86_64 上发生

我使用sleep & wait $!而不是简单的sleep来获得sleep信号的可中断性(如SIGUSR1)。但是wait当您运行以下命令时,bash-builtin 的行为似乎很奇怪。

1号航站楼:

cat <(
   trap 'echo SIGUSR1' SIGUSR1;
   echo $BASHPID;
   while :;do
       sleep 1 &
       wait $!;
       echo test;
   done
   )&
Run Code Online (Sandbox Code Playgroud)

2 号航站楼:

kill -10 /the pid of the subshell, printed by the previous command/
Run Code Online (Sandbox Code Playgroud)

1号航站楼:

^C (ctrl + C)
Run Code Online (Sandbox Code Playgroud)

然后,我得到了以 100% 消耗 CPU 的子外壳。

1号航站楼:

pkill -P $(pgrep -P $$)
Run Code Online (Sandbox Code Playgroud)

你知道为什么会发生这种行为吗?

注意 …

shell bash signals shell-script trap

17
推荐指数
1
解决办法
1403
查看次数

为什么在尝试捕获 SIGINT 信号时会收到错误消息?

我正在运行下面的脚本以使用 lftp 从服务器自动下载文件。它可以工作,但在运行时我收到错误消息

trap: SIGINT: bad trap
Run Code Online (Sandbox Code Playgroud)

如果我用 INT 和 TERM 替换 SIGINT 和 SIGTERM 那么它确实有效,但我不知道它是否达到了同样的目的。这是在 Linux Debian 4.9.2-10 上。

#!/bin/sh
login="login"
pass="password"
host="server.server.com"
remote_dir='~/remote/dir'
local_dir="/local/dir"

base_name="$(basename "$0")"
lock_file="/tmp/$base_name.lock"
trap "rm -f $lock_file" SIGINT SIGTERM
if [ -e "$lock_file" ]
then
    echo "$base_name is running already."
    exit
else
    touch "$lock_file"
    /usr/bin/lftp -p 22 -u "$login","$pass" sftp://"$host" << EOF
    set sftp:auto-confirm yes
    set mirror:use-pget-n 5
    mirror -c -P5 "$remote_dir" "$local_dir"
    quit
EOF
    rm -f "$lock_file"
    trap - SIGINT SIGTERM
    exit
fi
Run Code Online (Sandbox Code Playgroud)

shell trap

17
推荐指数
1
解决办法
1万
查看次数

陷阱命令中的信号 0 是什么?

我正在遵循有关如何使用 ssh-agent 设置无密码 SSH 身份验证的指南

要启动 ssh-agent,作者建议在 中使用以下代码.bash_profile

SSHAGENT=/usr/bin/ssh-agent
SSHAGENTARGS="-s"
if [ -z "$SSH_AUTH_SOCK" -a -x "$SSHAGENT" ]; then
    eval `$SSHAGENT $SSHAGENTARGS`
    trap "kill $SSH_AGENT_PID" 0
fi
Run Code Online (Sandbox Code Playgroud)

我不明白为什么它会捕获信号 0。根据man 7 signal没有这样的信号。

这只是一个错字或错误,还是真的有什么成就?

bash signals trap

15
推荐指数
1
解决办法
2万
查看次数

在后台静默启动任务

我知道你可以使用它在后台启动一个进程,而不会在进程被置于后台以及完成时收到通知:

(命令 &) &> /dev/null

但是,这会删除进程完成时捕获的选项 ( trap child_done CHLD)。

我怎么能两者兼得?

process zsh trap

15
推荐指数
2
解决办法
1万
查看次数