bash中的障碍,可以轻松完成吗?

时间:2012-02-04 23:25:42

标签: bash

假设我有一个bash脚本并行执行三个脚本

./script1 &
./script2 &
./script3 &

现在,让我们说./script4依赖于script1,script2和script3。我怎么能强迫它等待那些,同时仍然并行执行这三个脚本?

3 个答案:

答案 0 :(得分:8)

您可以在wait和其他一些shell中使用Bash内置命令。
(请参阅Windows上的等效命令WAITFOR

wait documentation

  

等待每个指定的进程完成并返回其终止   状态。

Syntax
      wait [n ...]
Key
   n   A process ID or a job specification
     

每个n可以是进程ID或作业规范;如果一份工作   给出了规范,该作业的管道中的所有进程都是   等待。

     

如果未给出n,则等待所有当前活动的子进程   for,返回状态为零。

     

如果n指定不存在的流程或作业,则返回状态为   127。否则,返回状态是最后一个进程或作业等待的退出状态。

简单解决方案

低于wait,无限期等待所有当前活动的子进程全部结束(即在这种情况下是三个脚本)。

./script1 &
./script2 &
./script3 &
wait       # waits for all child processes
./script4

将PID存储在shell局部变量

./script1 & pid1=$!
./script2 & pid2=$!
./script3 & pid3=$!
wait $pid1 $pid2 $pid3  # waits for 3 PIDs
./script4

将PID存储在临时文件

./script1 & echo $! >1.pid
./script2 & echo $! >2.pid
./script3 & echo $! >3.pid
wait $(<1.pid) $(<2.pid) $(<3.pid)
rm 1.pid 2.pid 3.pid            # clean up
./script4

最后一个解决方案使用三个文件(1.pid2.pid3.pid)污染当前目录。在wait调用之前,其中一个文件可能已损坏。此外,如果发生崩溃,这些文件可能会留在文件系统中。

答案 1 :(得分:6)

来自bash手册页:

wait [n ...]
    Wait for each specified process and return its termination status.
    Each `n` may be a process ID or a job specification.... If `n` is not
    given, all currently active child processes are waited for, and the return
    status is zero.

最简单的实现可能是您的上一个脚本启动其他脚本。这样它就可以很容易地存储它们的PID并将它们传递给wait

答案 2 :(得分:1)

几年前我很快就掀起了一些东西,但现在我想要嵌套的并行性。这就是我想出的:

# Run each supplied argument as a bash command, inheriting calling environment.
# bash_parallel's can be nested, though escaping quotes can be tricky -- define helper function for such cases.
# Example: bash_parallel "sleep 10" "ls -altrc"
function bash_parallel
{
    (   
        i=0
        unset BASH_PARALLEL_PIDS # Do not inherit BASH_PARALLEL_PIDS from parent bash_parallel (if any)

        for cmd in "$@"
        do
            ($cmd) &             # In subshell, so sibling bash_parallel's wont interfere
            BASH_PARALLEL_PIDS[$i]=$!
            echo "bash_parallel started PID ${BASH_PARALLEL_PIDS[$i]}: $cmd"
            i=$(($i + 1))
        done

        echo "bash_parallel waiting for PIDs: ${BASH_PARALLEL_PIDS[@]}"
        wait ${BASH_PARALLEL_PIDS[@]}
    ) # In subshell, so ctrl-c will kill still-running children. 
}

使用:

eisbaw@leno:~$ time (bash_parallel "sleep 10" "sleep 5")
bash_parallel started PID 30183: sleep 10
bash_parallel started PID 30184: sleep 5
bash_parallel waiting for PIDs: 30183 30184

real    0m10.007s
user    0m0.000s
sys 0m0.004s