【问题标题】:Trying to have a bash script timeout if a certain condition is not met如果不满足某个条件,则尝试使 bash 脚本超时
【发布时间】:2018-09-29 03:00:42
【问题描述】:

我正在尝试编写一个将执行的 bash 脚本,如果满足某个条件 (grep),则脚本退出,但如果在 X 秒内未找到 grep,那么我希望它回显某些内容,然后退出。最大的问题是其中的命令之一运行时间很长,我必须退出它,否则只会继续运行,直到我关闭终端。

为了提供帮助,我们正在使用 Pusher CLI https://pusher.com/docs/pusher_cli/documentation 在现场 ping IoT 设备。

为了使其正常工作,我首先订阅频道,然后将此过程置于后台,等待 5 秒,然后发送 ping。然后我greping 后台进程的输出并在响应中寻找“pong”,如果找到则退出。这一切都很好,我遇到的问题是找不到“pong”(设备脱机)并且订阅过程只是在后台无限期地运行,我不知道设备处于脱机状态。

所以我想要一些可以触发命令然后在 10 秒后杀死所有东西的东西,但是如果找到“pong”然后用这种方式杀死所有东西。

这是我到目前为止的脚本

ping () {
  subscribe_channel $1 &
  sleep 5
  ping_channel $1
}

ping_channel () {
  pusher channels apps trigger --app-id $appid --channel $1 --event $event --message $message
}

subscribe_channel () {
  while read -r line; do
    echo $line
    if [[ $(echo $line | grep "pong") ]]; then
      echo "online"
      exit
    fi
  done < <(pusher channels apps subscribe --app-id $appid --channel $1)
}

ping channel

【问题讨论】:

  • 顺便说一句,这里有很多引用错误。通过shellcheck.net 运行您的代码并修复它找到的内容。
  • 另外,如果您只想测试一行是否包含子字符串,[[ $line = *pong* ]] 实际上比在进程替换中运行调用 grep 的管道快几个数量级。

标签: bash


【解决方案1】:

您可以使用timeout 运行ping_channel 并在10 秒后退出。

如果一个命令由于超时而退出,那么它的返回码将是124,而不是0

这方面的一个例子:

timeout 1 sleep 10  # Try to sleep for 10 seconds but timeout after 1 second
echo $?  # Exits with a status of 124

timeout 2 sleep 1  # Sleep for 1 second, the timeout of 2 seconds is not hit
echo $?  # Exits with a status of 0

要在您的代码中使用它,请更改以下行:

pusher channels apps trigger --app-id $appid --channel $1 --event $event --message $message

到:

timeout 10 pusher channels apps trigger --app-id $appid --channel $1 --event $event --message $message
pusher_status=$?
if (( pusher_status == 124 )); then
    echo "ping_channel has timed out after 10 seconds"
fi

希望您可以使用上面的代码来处理您的代码。

编辑:

timeout 预装在某些 Linux 操作系统变体上,但如果没有,您可能需要安装它。

如果您无法安装它,那么以下 BashFAQ 上的一些解决方案可能会有所帮助:BashFAQ068(感谢 @CharlesDuffy)

【讨论】:

  • 在这种情况下使用算术构造 ((...)) 更好。所以,if ((pusher_status == 124)); then ....
  • 嗨@codeforester,谢谢。我很感兴趣——我一直使用[[..]] 进行算术运算。为什么使用((..)) 更好?
  • 您不需要$ 来扩展(( )) 中的变量,它还提供了更多操作。请记住,=(赋值)和==(( ... )) 内部并不相同。
  • 请注意,timeout 不是内置在 bash 中的——它是一个外部工具(并且没有被 POSIX 标准化,因此也保证由您的操作系统供应商提供)。您可能想告诉 OP 从哪里获取它,或者至少指定需要安装它才能使此答案起作用。
  • (对于涵盖timeout 和等效工具的规范、维护参考,我建议添加指向BashFAQ #68 的链接)。
猜你喜欢
  • 1970-01-01
  • 2015-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-16
  • 1970-01-01
相关资源
最近更新 更多