【发布时间】:2011-06-17 09:45:44
【问题描述】:
我想知道如果可能的话,我如何在 BASH 中创建一个简单的作业管理来并行处理多个命令。也就是说,我有一大串要运行的命令,我希望在任何给定时间运行其中的两个。
我对 bash 了解不少,所以下面是一些使它变得棘手的要求:
- 这些命令的运行时间是可变的,所以我不能只生成 2 个,等待,然后继续接下来的两个。一旦一个命令完成,就必须运行下一个命令。
- 控制进程需要知道每条命令的退出码,这样才能保存失败的总数
我正在考虑以某种方式使用trap,但我没有看到一种简单的方法来获取处理程序中子项的退出值。
那么,有什么想法可以做到这一点吗?
好吧,这里有一些应该可以工作的概念验证代码,但它会破坏 bash:生成无效的命令行、挂起,有时还会出现核心转储。
# need monitor mode for trap CHLD to work
set -m
# store the PIDs of the children being watched
declare -a child_pids
function child_done
{
echo "Child $1 result = $2"
}
function check_pid
{
# check if running
kill -s 0 $1
if [ $? == 0 ]; then
child_pids=("${child_pids[@]}" "$1")
else
wait $1
ret=$?
child_done $1 $ret
fi
}
# check by copying pids, clearing list and then checking each, check_pid
# will add back to the list if it is still running
function check_done
{
to_check=("${child_pids[@]}")
child_pids=()
for ((i=0;$i<${#to_check};i++)); do
check_pid ${to_check[$i]}
done
}
function run_command
{
"$@" &
pid=$!
# check this pid now (this will add to the child_pids list if still running)
check_pid $pid
}
# run check on all pids anytime some child exits
trap 'check_done' CHLD
# test
for ((tl=0;tl<10;tl++)); do
run_command bash -c "echo FAIL; sleep 1; exit 1;"
run_command bash -c "echo OKAY;"
done
# wait for all children to be done
wait
请注意,这不是我最终想要的,但会成为获得我想要的基础。
跟进:我已经用 Python 实现了一个系统来执行此操作。因此,任何使用 Python 编写脚本的人都可以拥有上述功能。参考shelljob
【问题讨论】:
-
您可以使用shell内置的'wait'命令来获取每个子进程并获取其退出状态,但您需要等待特定的pid,否则直到所有子进程都退出后才会返回。不过,您不想在信号处理程序中等待。这在 bash 中很棘手,老实说在 C 中更容易做到。
-
好吧,如果我能在信号处理程序中获得 PID,我想我会没事的,但无论如何我都看不到 PID。我知道它可以用其他语言轻松完成,但我正在尝试对 bash 脚本进行扩展。
标签: bash