【问题标题】:Execute a shell command from a shell script without stopping if error occurs如果发生错误,则从 shell 脚本执行 shell 命令而不停止
【发布时间】:2009-07-02 15:31:53
【问题描述】:

以一种尝试/捕获的形式,我想执行一个在发生错误时不会停止的 bash。

具体的bash是:

#!/bin/sh

invoke-rc.d tomcat stop

rm -fr /var/webapps/
cp -R $WEBAPP /var/webapps/
invoke-rc.d tomcat start

我想执行“invoke-rc.d tomcat stop”,即使Tomcat没有运行,继续执行其他bash命令。

【问题讨论】:

  • 这不是 bash 的默认行为吗?我可以发誓它是(如果某些命令失败,您需要采取明确的措施来终止脚本......)
  • 如果你执行这个脚本并且tomcat没有运行,这个脚本会因为第一个命令返回错误而停止执行。我希望脚本继续。
  • @Alex:这是默认设置,但有可能会覆盖默认设置。
  • 我和 Alex 在一起 - bash 行为不端,或者已配置为(错误)通过退出错误来表现。使用:'set +e' 来抵消 'set -e' 的影响(这意味着出错时终止)。并找出在您的环境设置中导致 bash 行为不端的原因 - 如果您的 shell 因第一个错误而退出,所有类型的脚本都会意外失败。

标签: linux bash error-handling


【解决方案1】:

试试:

invoke-rc.d tomcat stop > /dev/null 2>&1 || true

一点背景:

user@tower: # true
user@tower: # echo $?
0
user@tower: # false
user@tower: # echo $?
1

user@tower: # which true
/bin/true
user@tower: # which false
/bin/false

真正的解决方案是查看 tomcat 初始化脚本,看看它如何知道 tomcat 是否正在运行 :) 这样,您就不会不必要地纠缠它。

请参阅this post 关于取消设置/设置 +e 的其他建议。虽然它可以解决您眼前的问题,但您可能会发现您需要在自己的脚本中使用最近未设置的行为,尤其是在您复制文件时。

这是造成 true 和 false 的最大原因之一,除了使 Makefile 在各种构建环境中的行为符合预期。

另外,set +e 不是完全可移植的,即某些版本的 Solaris(甚至 Dash).. 但我怀疑这对你来说是一个问题。

【讨论】:

  • 我删除了你的代码和 root 用户的路径,因为有人可能认为你需要是 su。希望你不介意;)
  • @victor hugo - 谢谢。我编辑了这篇文章几次,并没有注意到我留下了机智的路径:)我今天一定是有点脑死了。
  • 我其实没看懂第2部分>&1 ||真的。我理解 > /dev/null 意味着错误被重定向到那里,但我既不理解语法也不理解另一部分的含义。你能解释一下吗?
  • @Toskan > /dev/nullstdout 重定向到/dev/null2>&1stderr 重定向到stdout,有效地将stdoutstderr 发送到空设备。 || true 确保命令以零状态退出,即使它失败。这就像说如果这不起作用,则运行/bin/true 并返回该值。这是一个合乎逻辑的OR。例如。 [ -d /etc ] || echo "your system is broken"(如果 /etc 不是目录,则回显)。
  • 是否将输出重定向到/dev/null 可选?我有一个 bash 脚本,它调用数据库客户端删除一些索引,导入大量数据,然后恢复索引。如果导入失败,我希望将这些索引放回原处,但我想查看输出并知道导入也失败了。在我调用set -e 后,打印到stderr 是否会导致我的脚本退出,或者我可以省略重定向吗?
【解决方案2】:

使用set +e 禁用“立即退出”选项,运行您的命令,然后可以选择使用set -e 重新启用它:

set +e
invoke-rc.d tomcat stop
set -e  # optional

请参阅 Bash 手册的 section 4.3.1 以了解对 set 内置函数及其所有各种选项(其中有很多选项)的解释。

【讨论】:

    【解决方案3】:

    使用 bash's set command 暂时禁用非零退出行为。

    set +e
    invoke-rc.d tomcat stop
    set -e
    

    【讨论】:

    • 你应该对你的脚本写一点解释。只需单击“编辑”。顺便说一句,欢迎来到 SO
    • set {args} 并不总是可移植的。但是,如果你这样做: set +e || { 处理脑死壳的代码 } 对于符合 POSIX 规范的任何东西来说,它都很好。一般来说,只使用 true / false 会更容易(也更便携)。
    【解决方案4】:

    如果 invoke-rc.d tomcat stop 是您想要防止失败的唯一事情,也许 invoke-rc.d tomcat stop ||真的 可以吗?那不应该有一个非零的退出状态。

    【讨论】:

      【解决方案5】:

      尝试将标准错误重定向到文件...类似于 2> myerror.

      【讨论】:

      • 如果看到类似命令 > /dev/null.是这样的吗?这将使命令的输出转到一个文件。但是否也捕获了错误?
      • 这并不能从错误中恢复,它只是隐藏了原因。
      猜你喜欢
      • 1970-01-01
      • 2012-01-06
      • 1970-01-01
      • 2011-10-04
      • 2019-03-18
      • 2018-02-27
      • 2018-03-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多