【问题标题】:Collecting process ids of parallel process in bash file在 bash 文件中收集并行进程的进程 ID
【发布时间】:2017-12-08 15:37:19
【问题描述】:

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

PROCESS_IDS=()

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

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

【问题讨论】:

  • 尝试删除前三行末尾的&
  • @pavel 我希望这四行并行运行。
  • 我只是问过你问过,它确实有效。但是,我想并行运行它们,我仍然可以从appendechos 中访问$1 变量,它只是没有正确存储到数组中。
  • process_ids+=( "$!" ) 是一种相当简洁的附加到数组的方法。
  • @ThomasReggi 如果您从末尾删除 &,睡眠仍将并行运行。它只是串行运行的数组的分配。

标签: bash shell pid


【解决方案1】:

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

process_ids=( )
append() { process_ids+=( "$1" ); }       # 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

【讨论】:

  • 虽然包含它们的风格可能不错,但大括号不是必需的。 sleep 1 && echo one & 等同于 { sleep 1 && echo one; } & 来自 bash 手册页:Of these list operators, && and || have equal precedence, followed by ; and &, which have equal precedence.
  • @WilliamPursell, nod -- 我在这里回归到“良好的风格” -- 我发现这对读者来说不那么模棱两可了行为。
【解决方案2】:

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

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

如果命令被控制运算符“&”终止,shell 会在子 shell 中异步执行命令。这称为在后台执行命令。

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

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

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

cat /tmp/file.*

编辑:这只是一个概念证明 - 无论如何都不要使用文件系统(正如威廉指出的那样,除非您注意唯一性和同步,否则这将容易出错)。我只是想说明您需要找到另一种从子shell 中获取信息的方法。

【讨论】:

  • 好主意,但将所有 pid 写入单个文件可能更简洁。 glob 扩展可能会拾取与此脚本完全无关的文件。
  • “猜测”是准确的——您可以考虑编辑它以更权威的语气说话。
猜你喜欢
  • 2018-01-16
  • 2021-07-26
  • 1970-01-01
  • 2012-02-25
  • 1970-01-01
  • 2014-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-12
相关资源
最近更新 更多