前几天在工作中写了个Bash脚本,启动一个web服务器,并在继续执行后续操作之前等待Server完成启动。
该脚本运行良好,我们没有遇到任何问题,直到我们遇到一个无限循环。
我们使用Bash内置的until来检查web服务器是否已启动:
1 | until curl --silent --fail-with-body 10.0.0.1:8080/health; do |
运行良好。除非web服务器在启动过程中崩溃,脚本会无限期地sleep 1。
这里有一个方便的工具:timeout。顾名思义,此命令会为其他命令添加超时。您可以指定要等待命令的时间限制,如果超过该时间,timeout会发送信号将其终止并以非零值退出。
默认情况下,timeout发送SIGTERM,但可以使用--signal标志更改它,例如timeout --signal=SIGKILL 1s foo。
例如,timeout 1s sleep 5将在1秒后向sleep发送SIGTERM信号:
1 | $ time timeout 1s sleep 4 |
接下来要做的就是结合timeout和until:
1 | timeout 1m until curl --silent --fail-with-body 10.0.0.1:8080/health; do |
唯一的问题是这不起作用。timeout需要一个可终止的命令,而until是一个shell关键字:你不能SIGTERM``until。我们不能将timeout与任何shell内置命令一起使用。
可行的一个方案是将该until包装在一个Bash进程中:
1 | timeout 1m until curl --silent --fail-with-body 10.0.0.1:8080/health; do |
另一种方法是将until移动到一个单独的Bash脚本中并对其进行timeout:
1 | timeout 1m ./until.sh |
很遗憾我们不能直接将timeout与until一起使用,那样会很棒。但是将其包装在Bash进程/脚本中可以完成这项工作。