如何运行失败后不退出的命令,直到成功?

Posted

技术标签:

【中文标题】如何运行失败后不退出的命令,直到成功?【英文标题】:How Can I Run A Command That Does Not Exit Upon Failure Until It Succeeds? 【发布时间】:2016-10-08 11:35:59 【问题描述】:

我有一个运行HBaseDocker 容器,有关它的更多详细信息,请参阅here。基本上,HBase 大约需要 30 秒才能激活。

显然,我还有其他容器取决于这个容器。其中之一,docker-entrypoint.sh 我基本上是这样做的:

#!/bin/bash

/path/to/command argument

while [ $? -ne 0 ]; do
  sleep 2;
  /path/to/command argument
done

这里的问题是/path/to/command 是部署网络服务器的东西,它将与HBase 容器交互。如果成功,它会阻塞当前进程(这很好,因为它在容器中),但同样,如果失败,它会打印堆栈跟踪但不会以一些-ne 0 代码退出(实际上,根本不退出)。事实上,如果它退出 --restart=always 就会处理它。

所以,我的问题是,我怎样才能让它一直重试直到它成功,基本上不退出一些失败代码?退出Docker 容器也是一个选项,这样它就可以一直重启直到成功。目前,我没有机会修改未退出代码退出。

更新:

我不得不这样做:

#!/bin/bash

tmp=$(mktemp)
/path/to/command args 2> "$tmp" &

while true; do
  sleep 5;
  if [ -s "$tmp" ]; then
    exit
  fi
done

基本上,我必须在后台运行它,这样上面的脚本才能继续执行(path/to/command 是一个 UI 阻塞命令 - 例如服务器的 listen - 成功时不会退出 - 它会监听 -也不是当它失败时——它应该有,这就是我问这个问题的原因——)。

所以为了让 Docker 容器不退出,我必须添加一个while true; 循环,在其中我检查$tmp 中是否有错误。如果有,我就直接exit

更新 2:

我将 bash 脚本更改为:

#!/bin/bash

/path/to/command args &

while true; do
  sleep 10;
  
  response=$(curl --write-out %http_code --silent --output /dev/null http://localhost);

  if [ "$response" != "200" ]; then
    exit
  fi
  
done

因为我的容器正在部署一个 Web 服务器,所以我至少在启动它之后在主线程中监控它的状态。仍有改进的余地。

【问题讨论】:

旁注:This 和其他一些人对退出进程提出了相同的问题。 也许能够将stderr重定向到一个文件,然后检查该文件是否为空。 @andlrc 聪明。我会尽快尝试。 您也可以将其作为后台进程运行并加入警报... @Will,我可以将它作为后台进程运行,但不太明白/知道您加入警报的意思。 【参考方案1】:

您可以尝试将stderr 重定向到一个文件,然后检查该文件是否为空:

tmp=$(mktemp)
/path/to/command argument 2> "$tmp"

# Run code until "$tmp" is empty
until [ -s "$tmp" ]; do
  sleep 2
  /path/to/command argument 2> "$tmp"
done

rm "$tmp"

【讨论】:

当我要再次运行命令时,我是否应该不清除$tmp @HasanCanSaral 2> 应该为您做到这一点。考虑echo 1 > a;echo 2> a; od a; 将输出0000000 意味着它是空的 一个简单的问题,我最终会遇到几个卡住的进程,一个在成功后运行吗?当$tmp 不为空时,我怎么能设法从Dockercontainer 退出,我认为这是一个更好的选择? @HasanCanSaral 您的进程将在打印堆栈跟踪时终止,如果他们不这样做,您的代码将如何继续执行?而until循环会在tmp文件不为空时结束,然后删除文件。然后退出。 问题是他们没有。他们打印堆栈跟踪并挂起,这就是我问这个问题的原因。如果他们要终止​​,我不会有这个问题,因为 Docker 容器会退出然后重新启动。我不得不像上面那样做(参见编辑后的帖子),但对此不太满意。

以上是关于如何运行失败后不退出的命令,直到成功?的主要内容,如果未能解决你的问题,请参考以下文章

如果 errexit 打开,我如何运行可能失败的命令并获取其退出代码?

错误:链接器命令失败,退出代码为 1(使用 -v 查看调用):在 Macbook [重复]

Cocoapods错误:链接器命令失败,退出代码为1(使用-v查看调用)

关闭终端后不退出“连接被拒绝”错误。姜戈 1.8

核心数据:NSManagedObjectContext 未保存/获取请求失败,直到应用退出和重新启动

android目标:android:命令失败,退出代码为enoent Meteor