我最近发布了一个问题,询问prevent PID's from being re-used是否可能。

到目前为止,答案似乎是否定的。 (可以)

但是,用户Diego Torres Milano添加了该问题的答案,而我的问题是关于该答案的。

迭戈回答,



我实际上不明白为什么迭戈在这里使用了4194303这个数字,但这是另一个问题。

我的理解是以下代码有问题:

for pid in "${PIDS[@]}"
do
    wait $pid
done

问题是我在一个数组中有多个PID,并且for循环将与数组中的每个PID依次运行wait命令,但是我无法预测进程将以其PID存储在此顺序的顺序完成大批。

IE;可能发生以下情况:
  • 开始等待数组索引0中的PID
  • 数组索引1中具有PID的进程终止
  • 新作业在系统上运行,导致存储在PID数组索引1中的PID被重用于另一个进程
  • wait终止,因为数组索引0中的PID退出
  • 开始等待数组索引0中的PID,只是现在这是一个不同的过程,我们不知道它是什么
  • 重新使用wait当前正在等待的PID的运行过程永远不会终止。可能是邮件服务器的PID或系统管理员已启动的东西。
  • wait一直等待,直到找到下一个严重的Linux错误并重新启动系统或断电为止

  • 迭戈说:



    IE;我上面描述的情况不会发生。

    迭戈是正确的吗?
  • 如果是这样,为什么我上面描述的情况不会发生?

  • 还是迭戈不正确?
  • 如果可以,那么我今天晚些时候发布一个新问题...

  • 补充笔记

    在我看来,这个问题可能令人困惑,除非您知道PID是后台启动的进程的PID。 IE;
    my_function &
    PID="$!"
    PIDS+=($PID)
    

    最佳答案

    让我们来看看您的选择。

    无条件等待所有后台作业

    for i in 1 2 3 4 5; do
        cmd &
    done
    wait
    

    这具有简单的好处,但是您不能使计算机忙碌。如果要在旧工作完成后开始新工作,则不能。在完成所有后台作业之前,您的机器利用率越来越低,此时您可以开始一批新的作业。

    与此相关的是通过将多个参数传递给wait来等待一部分作业的能力:
    unrelated_job &
    for i in 1 2 3 4 5; do
      cmd & pids+=($!)
    done
    wait "${pids[@]}"   # Does not wait for unrelated_job, though
    

    以任意顺序等待单个作业
    for i in 1 2 3 4 5; do
       cmd & pids+=($!)
    done
    
    for pid in "${pids[@]}"; do
       wait "$pid"
       # do something when a job completes
    done
    

    这样做的好处是可以让您在工作完成后进行工作,但是
    仍然存在一个问题,即除$pid之外的其他作业可能会首先完成,从而使您的计算机未得到充分利用,直到$pid实际完成为止。但是,即使它确实在您实际等待之前完成,您仍然会获得每个作业的退出状态。

    等待下一个作业完成(bash 4.3或更高版本)
    for i in 1 2 3 4 5; do
       cmd & pids+=($!)
    done
    
    for pid in "${pids[@]}"; do
       wait -n
       # do something when a job completes
    done
    

    在这里,您可以等待作业完成,这意味着您可以使计算机尽可能地繁忙。唯一的问题是,您不必使用jobs即可获取事件进程的列表并将其与pids进行比较,而不必知道已完成的作业。

    还有其他选择吗?

    Shell本身并不是进行作业分配的理想平台,这就是为什么要设计许多用于管理批处理作业的程序的原因:xargsparallelslurmqsub等。

    10-02 03:30
    查看更多