在 bash 文件中收集并行进程的进程 ID

Collecting process ids of parallel process in bash file

下面我有一个脚本,它收集各个命令的进程 ID,并将它们附加到 bash 中的数组。出于某种原因,正如您在下面看到的标准输出,最终结果数组只包含一项,即最新的 id。此脚本末尾的结果 PROCESS_IDS 数组如何包含所有四个进程 ID?

PROCESS_IDS=()

function append {
    echo 
    PROCESS_IDS=("${PROCESS_IDS[@]}" )
}

sleep 1 && echo 'one' & append $! &
sleep 5 && echo 'two' & append $! &
sleep 1 && echo 'three' & append $! &
sleep 5 && echo 'four' & append $!
wait

echo "${PROCESS_IDS[@]}"

这是标准输出:

83873
83875
83879
83882
three
one
four
two
83882

我的猜测是每当你向后台发送函数调用时,它都有自己的全局变量副本,所以他们将 PID 附加到四个PROCESS_IDS 的独立副本。这就是为什么每个函数调用都会发现它是空的,并在其中存储一个 PID。

http://www.gnu.org/software/bash/manual/bashref.html#Lists

If a command is terminated by the control operator ‘&’, the shell executes the command asynchronously in a subshell. This is known as executing the command in the background.

如果您想收集所有四个函数调用的输出,让它们写入磁盘并在最后读取输出:

function append {
    echo  | tee /tmp/file.
}

sleep 1 && echo 'one' & append $! &
sleep 5 && echo 'two' & append $! &
sleep 1 && echo 'three' & append $! &
sleep 5 && echo 'four' & append $!
wait

cat /tmp/file.*

编辑:这只是一个概念验证——无论如何不要用文件系统来做(正如 William 指出的那样,这很容易出错,除非你采取注意唯一性和同步性)。我只是想说明您需要找到另一种从子外壳中获取信息的方法。

不要将 append 操作本身发送到后台。在 & 之后 你想要背景的内容但是 之前 append 就足够了: sleepecho 仍在后台,但 append 不是。

process_ids=( )
append() { process_ids+=( "" ); }       # POSIX-standard function declaration syntax

{ sleep 1 && echo 'one'; } & append "$!"
{ sleep 5 && echo 'two'; } & append "$!"
{ sleep 1 && echo 'three'; } & append "$!"
{ sleep 5 && echo 'four'; } & append "$!"

echo "Background processes:"              # Demonstrate that our array was populated
printf ' - %s\n' "${process_ids[@]}"

wait