【问题标题】:Catching all bad signals for called commands in Bash script捕获 Bash 脚本中调用命令的所有不良信号
【发布时间】:2015-07-22 17:40:34
【问题描述】:

我们正在为构建服务器创建一个 bash 脚本。我们希望确保当我们在脚本中执行 bash 命令时,它会返回信号 0。如果没有,我们希望停止执行。到目前为止,我们的解决方案是:

#some command
if [ $? -ne 0 ] ; then
    #handle error
fi

每个命令之后可能会导致此问题。这使得代码很长并且看起来不是很优雅。也许我们可以使用 bash 函数。虽然使用 $?可能有点棘手,我们仍然必须在每个命令之后调用该函数。有没有更好的办法?我查看了 trap 命令,但它似乎只对我正在编写的 bash 脚本进行信号处理,而不是我调用的任何命令。

【问题讨论】:

  • $? 是退出代码。退出代码和信号不相关。

标签: bash error-handling signals


【解决方案1】:

执行此操作的稳健、规范的方法是:

#!/bin/bash
die() {
  local ret=$?
  echo >&2 "$*"
  exit "$ret"
}

./configure  || die "Project can't be configured"
make         || die "Project doesn't build"
make install || die "Installation failed" 

执行此操作的脆弱、便捷的方法是set -e

#!/bin/bash
set -e     # Script will exit in many (but not all) cases if a command fails

./configure
make
make install

或等效(带有自定义错误消息):

#!/bin/bash
# Will be called for many (but not all) commands that fail
trap 'ret=$?; echo >&2 "Failure on line $LINENO, exiting."; exit $ret' ERR

./configure
make
make install

对于后两者,脚本不会退出任何属于条件语句或&&/||的命令,所以while:

backup() {
  set -e
  scp backup.tar.gz user@host:/backup
  rm backup.tar.gz
}
backup

如果传输失败,将正确避免执行rm,稍后插入这样的功能:

if backup
then
  mail -s "Backup completed successfully" user@example.com
fi

将使backup 在失败时停止退出并意外删除备份。

【讨论】:

  • 这行得通!谢谢您的帮助。我可能会使用第三个。 ERR 是否只捕获任何非零信号?如果是这样,我是否也可以为其他信号设置陷阱,例如在 SIGSEGV 上显示特定消息,并使其优先于默认的 ERR 陷阱?
  • ERR 根本没有捕捉到任何信号。它在命令返回非零退出代码时触发。退出代码和信号是不同的东西。被信号 SIGSEGV (11) 杀死的进程与以代码 11 退出的进程没有任何关系。
  • 好的。在编写脚本时,我们会牢记这一点和最近的编辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-24
  • 1970-01-01
  • 2023-03-23
  • 2021-07-04
  • 2011-01-10
  • 1970-01-01
相关资源
最近更新 更多