我最近发布了一个问题,询问是否可以prevent PID's from being re-used。
到目前为止答案似乎是否定的。 (没关系。)
但是,用户Diego Torres Milano添加了该问题的答案,我的问题就是答案。
迭戈回答说,如果您害怕重复使用PID,那么等待时就不会发生这种情况 其他答案解释,你可以使用
echo 4194303 > /proc/sys/kernel/pid_max
减少你的恐惧; - )
我实际上并不理解迭戈为什么在这里使用了数字4194303
,但这是另一个问题。
我的理解是我遇到了以下代码的问题:
for pid in "${PIDS[@]}"
do
wait $pid
done
问题是我在一个数组中有多个PID,并且for循环将按顺序运行wait
命令与数组中的每个PID,但我无法预测进程将以相同的顺序完成他们的PID存储在这个数组中。
即;以下可以发生:
wait
终止,因为数组索引0中的PID退出wait
当前正在等待永远不会的PID的运行过程终止。也许它是邮件服务器的PID或系统管理员已启动的东西。wait
一直等到找到下一个严重的linux bug并重新启动系统或停电如果你等待其他答案解释
,这将不会发生
即;我上面描述的情况不可能发生。
迭戈是否正确?
或者迭戈不正确吗?
我发现这个问题可能会令人困惑,除非你知道PID是后台启动的PID过程。即;
my_function &
PID="$!"
PIDS+=($PID)
答案 0 :(得分:22)
让我们来看看你的选择。
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本身并不是进行工作分配的理想平台,这就是为什么有大量程序用于管理批处理作业的原因:xargs
,parallel
,slurm
, qsub
等等。
答案 1 :(得分:0)
这是旧的,但是由于pid冲突导致延迟wait
等待一些随机无关的进程的情况尚未得到直接解决。
在内核级别是不可能的。它的工作方式是在父进程调用wait(2)
¹之前,子进程仍然存在。因为孩子仍然存在,linux将耗尽pid而不是重用它。这有时会出现所谓的僵尸或“失效”过程 - 这些孩子已经退出但尚未被父母“收获”。
现在,在shell级别,您无需调用wait(1)
¹即可获取子进程 - bash
会自动执行此操作。我还没有确认,但是当你为很久以前退出的儿童pid运行wait $pid
时,我会打赌bash
意识到它已经收获了那个孩子并立即返回信息而不是等待任何事情。
¹wait(N)
符号是用于消除API层之间歧义的约定 - N指的是命令/函数所在的手册部分。在这种情况下,我们有:
wait(2)
:系统调用 - 请参阅man 2 wait
wait(1)
:shell命令 - 请参阅man 1 wait
或help wait
如果您想知道每个手册部分的内容,请尝试man N intro
。