【问题标题】:Handle exceptions in bash scripts处理 bash 脚本中的异常
【发布时间】:2022-03-18 06:46:14
【问题描述】:

我有一个 bash 脚本(由 Jenkins 执行),它在某一时刻调用

local STATUS=$($SERVER_DIR/bin/jboss-cli.sh --controller=$WILDFLY_CONTROLLER --connect --user=$ADMIN_USER --password=$ADMIN_PW command=:shutdown --timeout=$JBOSSTIMEOUT);

这个 sn-p 的唯一目的是关闭正在运行的 Wildfly 进程。如果调用本身成功,但无论出于何种原因,wildfly 都没有终止,我还添加了另一项检查,几秒钟后执行

SERVER_PID=`ps aux | grep $SERVER_DIR | grep 'wildfly.xml' | grep -v grep | tr -s ' ' | cut -d ' ' -f 2`;
if [[ ! -z $SERVER_PID ]] ; then
        kill -9 $SERVER_PID;
    fi

但是,有时 - 我无法弄清楚在哪种情况下 - sn-p 的行为与预期不同。

问题类型 1)

调用 jboss-cli.sh 导致异常

> 2019-02-27_22-05-17 [INFO] Trying to stop wildfly service with jboss-cli.sh
/opt/wildfly/bin/jboss-cli.sh --controller=10.0.1.1:9990 --connect --user=XXXX --password=XXXX command=:shutdown --timeout=120
org.jboss.as.cli.CliInitializationException: Failed to connect to the controller
    at org.jboss.as.cli.impl.CliLauncher.initCommandContext(CliLauncher.java:278)
    at org.jboss.as.cli.impl.CliLauncher.main(CliLauncher.java:241)
    at org.jboss.as.cli.CommandLineMain.main(CommandLineMain.java:34)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.jboss.modules.Module.run(Module.java:312)
    at org.jboss.modules.Main.main(Main.java:460)
Caused by: org.jboss.as.cli.CommandLineException: The controller is not available at 10.0.1.27:9990
    at org.jboss.as.cli.impl.CommandContextImpl.tryConnection(CommandContextImpl.java:1028)
    at org.jboss.as.cli.impl.CommandContextImpl.connectController(CommandContextImpl.java:840)
    at org.jboss.as.cli.impl.CommandContextImpl.connectController(CommandContextImpl.java:819)
    at org.jboss.as.cli.impl.CliLauncher.initCommandContext(CliLauncher.java:276)
    ... 8 more
Caused by: java.io.IOException: java.net.ConnectException: JBAS012144: Could not connect to http-remoting://10.0.1.1:9990. The connection timed out
    at org.jboss.as.controller.client.impl.AbstractModelControllerClient.executeForResult(AbstractModelControllerClient.java:129)
    at org.jboss.as.controller.client.impl.AbstractModelControllerClient.execute(AbstractModelControllerClient.java:71)
    at org.jboss.as.cli.impl.CommandContextImpl.tryConnection(CommandContextImpl.java:1005)
    ... 11 more
Caused by: java.net.ConnectException: JBAS012144: Could not connect to http-remoting://10.0.1.1:9990. The connection timed out
    at org.jboss.as.protocol.ProtocolConnectionUtils.connectSync(ProtocolConnectionUtils.java:119)
    at org.jboss.as.protocol.ProtocolConnectionManager$EstablishingConnection.connect(ProtocolConnectionManager.java:256)
    at org.jboss.as.protocol.ProtocolConnectionManager.connect(ProtocolConnectionManager.java:70)
    at org.jboss.as.protocol.mgmt.FutureManagementChannel$Establishing.getChannel(FutureManagementChannel.java:204)
    at org.jboss.as.cli.impl.CLIModelControllerClient.getOrCreateChannel(CLIModelControllerClient.java:169)
    at org.jboss.as.cli.impl.CLIModelControllerClient$2.getChannel(CLIModelControllerClient.java:129)
    at org.jboss.as.protocol.mgmt.ManagementChannelHandler.executeRequest(ManagementChannelHandler.java:117)
    at org.jboss.as.protocol.mgmt.ManagementChannelHandler.executeRequest(ManagementChannelHandler.java:92)
    at org.jboss.as.controller.client.impl.AbstractModelControllerClient.executeRequest(AbstractModelControllerClient.java:236)
    at org.jboss.as.controller.client.impl.AbstractModelControllerClient.execute(AbstractModelControllerClient.java:141)
    at org.jboss.as.controller.client.impl.AbstractModelControllerClient.executeForResult(AbstractModelControllerClient.java:127)
    ... 13 more
packet_write_wait: Connection to XXX.XXX.XXX.XXX port 22: Broken pipe
Build step 'Execute shell' marked build as failure

这反过来会中止 bash 脚本,从而中止 Jenkins 作业。 那么,问题 1:如何捕获异常并确保处理 bash 脚本并使用 kill-switch 终止 wildfly。

问题类型 2)

有时通话冻结,控制台只显示我

2019-02-27_22-05-17 [INFO] 尝试使用 jboss-cli.sh 停止 wildfly 服务 /opt/wildfly/bin/jboss-cli.sh --controller=10.0.1.1:9990 --connect --user=XXXX --password=XXXX command=:shutdown --timeout=120

jboss 的 timeout 属性似乎没有正常工作。 那么,问题 2:如何确保呼叫已终止并且不会无限期地运行/等待?

谢谢, 理查德

【问题讨论】:

  • bash 中没有例外。很可能你得到一个状态码 != 0 并且你的脚本正在某处检查该值。如果您想要更全面的答案,请发布您的脚本代码。
  • 另外,请将每个问题作为一个单独的问题发布到 stackoverflow 上。

标签: bash jenkins jboss wildfly


【解决方案1】:

虽然不完全相同,但可以在 bash 中使用trap 在一定程度上模拟异常样式的行为。

在你尝试这些之前,最好真正理解它们,所以我强烈推荐你参考Bash manual,尤其是conditionals测试过的退出代码的概念。

我通常使用这样的东西:

trap 'echo >&2 "ERROR in $BASH_SOURCE at line $LINENO, Aborting"; exit $LINENO;' ERR

ERR(通常不区分大小写)是 bash 中的一个特殊触发器,当执行的命令返回 uncaught 错误时,它将调用其上设置的任何陷阱代码。例如:

$: trap 'echo OW' err
$: false
OW

false 总是返回 1 的退出代码,因此除非被捕获,否则它会触发陷阱,如下所示:

$: trap 'echo OW' err
$: false || echo nope
nope

|| 与条件链接底部的 && 一起被提及,但基本上,
&& 如果左侧表达式返回 true - a @ 则计算它的右侧表达式987654334@ 退出状态。 如果左侧表达式返回 false - 非零 退出状态,|| 将评估它的右侧表达式。 其中任何一个都会捕获(消耗)错误,阻止它触发陷阱,就像大多数关于退出状态的条件测试一样。

所以 - 假设文件 xmp 的内容为“Hello”,并且上面的陷阱已经到位。

$: echo Hello>xmp                                  # create simple file
$: grep foo xmp                                    # uncaught fail will trigger trap
OW
$: grep Hello xmp                                  # success doesn't trigger trap
Hello
$: if grep foo xmp; then echo ok; else echo no; fi # caught exception doesn't trigger trap
no
$: grep Hello xmp && echo ok || echo no            # success, no trigger
Hello
ok
$: grep foo xmp && echo ok || echo no              # caught, no trigger
no
$: grep foo xmp || false                           # LHS caught, RHS triggers trap
OW
$: grep Hello xmp || false                         # LHS doesn't trigger RHS, no error, no trigger
Hello
$: grep foo xmp ||:                                # explicit ignore, : is an alias for true
# WATCH OUT FOR THIS ONE -
$: grep foo xmp && echo ok                         # CHECKED, so *caught*
# note no trigger on the last one, because it was tested, even if not explicitly handled...

这些可能对您有多大帮助,也可能对您没有多大帮助,但能够对任何未捕获的错误采取常设行为,然后明确处理任何您知道可能会失败但您可以修复的事情,或者这并不是真的问题。

只要确保您了解它在做什么以及它是如何工作的,就不会让您感到惊讶。始终测试它是否符合您的预期。

【讨论】:

    猜你喜欢
    • 2011-10-21
    • 1970-01-01
    • 1970-01-01
    • 2017-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-22
    相关资源
    最近更新 更多