【问题标题】:Parallel run and wait for pocesses from subshell并行运行并等待来自 subshel​​l 的进程
【发布时间】:2020-07-14 10:02:25
【问题描述】:

大家好/我正在尝试为 shell 制作类似 parallel 工具,只是因为 parallel 的功能不足以完成我的任务。原因是我需要运行不同版本的编译器。 想象一下,我需要用不同的编译器编译 12 个程序,但我只能同时运行其中的 4 个(否则 PC 会耗尽内存并崩溃 :)。我还希望能够观察每次编译发生了什么,因此我在新窗口中执行每个编译。 只是为了在这里更容易,我将用等待并返回它的进程 id 的小脚本替换我运行的编译器 sleep.sh

#!/bin/bash
sleep 30 
echo $$

所以主脚本应该看起来像 parallel_run.sh

#!/bin/bash
for i in {0..11}; do
  xfce4-terminal -H -e "./sleep.sh" &
  pids[$i]=$!
  pstree -p $pids
  if (( $i % 4 == 0 ))
  then
    for pid in ${pids[*]}; do 
      wait $pid
    done
  fi
done

问题在于 $!我得到 xfce4-terminal 的 pid 而不是它执行的程序。因此,如果我查看第一次迭代的 ptree,我可以看到主脚本的输出:

xfce4-terminal(31666)----{xfce4-terminal}(31668)
                      |--{xfce4-terminal}(31669)

sleep.sh 说它当时有 pid = 30876。因此,在这种情况下等待根本不起作用。

问:如何获得在 subshel​​l 中运行的编译器的正确 PID? 也许还有其他方法可以解决这样的任务?

【问题讨论】:

  • 你为什么要在自己的终端中运行这些进程?如果您真的想这样做,请将编译器的调用包装到一个小的 shell 脚本中,该脚本检索 PID,并将其存储在某个文件中。然后,您的parallel_run.sh 可以从文件中检索要监控的 PID。或者,在编译器完成后确保终端关闭(即终止)。在这种情况下,等待终端无论如何都是正确的选择。
  • 我想在不同的终端中运行进程,只是为了不搞乱所有进程的输出......同时也让进程休整。将 PID 从子进程保存到文件中应该可以工作。但我宁愿等到终端关闭,因为这个解决方案看起来更简单。尽管如此,我无法获得正在运行的终端的 PID。看起来 xfce4-terminal 使进程称为 sleep.sh ,然后 xfce4-terminal 不知何故消失了。从我分享的 ptree 中你可以看到 31666 生成 31668 和 31669,但它们只出现片刻,其余的睡眠时间只有 sleep.sh 进程。
  • 如果您只想让它们的输出不碍事,请使用nohup 运行它们或将输出手动保存在文件中。

标签: linux bash shell sh pid


【解决方案1】:

如果您在新的 xfce4-terminal 中调用进程,因为终端进程在执行给定命令后立即死亡,似乎没有办法从父进程到子进程跟踪 PID。所以我找到了一个不完美但在我的情况下可以接受的解决方案。我运行并将编译器的进程置于后台并将输出重定向到 .log 文件。然后我在这些日志文件上运行 tail 并在当前批次的编译器完成时杀死属于当前 $USER 的所有尾巴,然后运行另一批次。

#!/bin/bash
for i in {1..8}; do
  ./sleep.sh > ./process_$i.log &
  prcid=$!
  xfce4-terminal -e "tail -f ./process_$i.log" &
  pids[$i]=$prcid
  if (( $i % 4 == 0 ))
  then
    for pid in ${pids[*]}; do 
      wait $pid
    done
  killall -u $USER tail
  fi
done

希望那时不会有其他尾巴在运行:)

【讨论】:

    猜你喜欢
    • 2018-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-31
    • 1970-01-01
    • 1970-01-01
    • 2011-06-21
    相关资源
    最近更新 更多