【问题标题】:Wait for multiple bash functions to finsih or exit them on timeout等待多个 bash 函数完成或超时退出
【发布时间】:2020-08-15 23:35:09
【问题描述】:

有一个我在循环中并行调用的函数:

#!/bin/bash

my_func()
{
    until [[ $entity status is OK ]]; do
        sleep 5
        echo "count=$count"
        if (( timeout_flag == 1 )); then
            break
        fi
    done
}

_arr=(e1 e2 e3)
count=0
timeout=60
timeout_flag=0

for entity in "${_arr[@]}"; do
    my_func "${entity}" &
done

while [[ "${count}" -lt "${timeout}" ]]; do
    sleep 5
    count=count+5
done
timeout_flag=1
echo "Timeout reached"
sleep 1

我希望所有函数定期检查直到实体的状态正常,然后等待所有正常状态或在达到超时时停止所有(剩余)函数?无论什么都先到。以上似乎不起作用,我需要手动杀死它。

  • 为什么我在最后得到"Timeout reached" 回显,而脚本没有等待函数完成?

  • 为什么 count=0 在 my_func 中并没有增加?

【问题讨论】:

  • 将您的脚本复制并粘贴到shellcheck.net 以查看您的错误,并阅读有关子shell 以了解您的逻辑为何不起作用。
  • 睡眠循环的意义何在?它不检查任何东西,只是(在修复后)增加一个变量并再次休眠......另外,请查看timeout 命令?
  • @Keldorn 我想增加计数器,所以一旦达到超时,我可以设置运行函数的标志
  • 注意count=count+5不是很有用;它将字符串"count+5" 分配给变量count。您可能想到了count=$(($count + 5)) 或主题的变体,例如((count += 5))

标签: bash shell


【解决方案1】:

如果想让每个函数在60秒后超时,可以使用timeout命令;它正是为此而生的:

#!/bin/bash                                                                                                                                                                                   

my_func() {
    to_sleep=$1
    stdbuf -oL echo "Request to sleep at least $to_sleep s"
    slept=0
    while [[ $slept -lt $to_sleep ]]; do
        sleep 1
        slept=$((slept + 1))
    done
    echo "Successfully slept $slept s ($to_sleep s requested)"
}

export -f my_func

_arr=(1 3 5)
maxtime=4s

for entity in "${_arr[@]}"; do
    stdbuf -oL echo "Launching with $entity s"
    timeout $maxtime bash -c "my_func $entity" &
done

输出是

Launching with 1 s
Launching with 3 s
Launching with 5 s
Request to sleep at least 1 s
Request to sleep at least 3 s
Request to sleep at least 5 s
Successfully slept 1 s (1 s requested)
Successfully slept 3 s (3 s requested)

请注意,“5 s”案例没有成功。

注意事项:

  • stdbuf -oL 在这里直接刷新回显输出
  • 添加export -f my_functimeout $maxtime bash -c 以使您的功能在timeout 启动的新shell 中可见,紧随this answer

【讨论】:

  • 我收到timeout: failed to run command ‘my_func’: No such file or directory
  • @lubik my_func 是您要调用的函数。替换成你想要的。
  • 这就是我正在做的,my_func 是我的函数的名称
  • @lubik 糟糕,该功能不可用。我使用this answer更新了我的答案。
  • 谢谢你,就像一个魅力。我有另一个错字 - 在双引号内的超时命令末尾有“&”。但是,我需要在终端中按 Enter 键才能返回到主 shell,因为子 shell 会显示它们的输出,直到它们超时。这会自动工作吗?例如在 Jenkins 中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-12
  • 2012-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多