【问题标题】:Bash: Is it possible to stop a PID from being reused?Bash:是否有可能阻止 PID 被重用?
【发布时间】:2017-03-14 13:58:23
【问题描述】:

是否可以阻止 PID 被重复使用?

例如,如果我在后台使用myjob & 运行作业myjob,并使用PID=$! 获取PID,是否可以阻止Linux 系统重新使用该PID,直到我检查了PID 不再存在(进程已结束)?

换句话说,我想做这样的事情:

myjob &
PID=$!
do_not_use_this_pid $PID
wait $PID
allow_use_of_this_pid $PID

想要这样做的原因在上面给出的示例中没有多大意义,但可以考虑连续启动多个后台作业,然后等待它们全部完成。

一些程序员老兄正确地指出,没有两个进程可以共享相同的 PID。这是正确的,但不是我在这里问的。我要求一种防止在使用特定 PID 启动进程后重新使用 PID 的方法。然后还有一种方法可以在我用完之后重新启用它,以检查我的原始过程是否完成。

既然被要求了,这里有一个用例:

  • 启动多个后台作业
  • 获取后台作业的 PID
  • 防止 PID 在后台作业终止后被另一个进程重新使用
  • 检查“后台作业”的 PID - 即确保后台作业完成
  • [请注意,如果为后台作业的 PID 禁用 PID 重用,则这些 PID 不能被在后台进程终止后启动的新进程使用]*
  • 重新启用后台作业的 PID
  • 重复

*进一步说明:

  • 假设启动了 10 个工作
  • 作业 5 退出
  • 另一个用户启动的新进程,例如,他们登录到一个 tty
  • 新进程的 PID 与 Job 5 相同!
  • 现在我们的脚本检查 Job 5 是否终止,但看到 PID 正在被 tty 使用!

【问题讨论】:

  • 内核已经不允许它了。没有两个进程可以有相同的 pid。
  • @Someprogrammerdude 好的,我解释得不够清楚,我会编辑我的问题,一秒钟
  • 也许您可以添加用例?告诉我们您要解决什么问题?关于the XY problem的相关阅读
  • 如果可以,我会写一个炸弹:for x in $(seq 1 PID_MAX); do do_not_use_this_pid $x; done
  • 您可能可以使用trap ... SIGCHLD 来异步处理子PID 终止。这样,您就不必担心 PID 在终止后以及在检查其状态之前会被重用。你只需要真正在你的脚本中小心启动子进程。

标签: linux bash pid


【解决方案1】:

如果您害怕重复使用 PID,如果您 wait 正如其他答案所解释的那样,则不会发生这种情况,您可以使用

echo 4194303 > /proc/sys/kernel/pid_max

减少你的恐惧;-)

【讨论】:

  • 除非我在这里不明白,如果我必须 wait 获得超过 1 个 PID,那么在等待命令无序完成的情况下,可能会重用另一个 PID
【解决方案2】:

解决此问题的进一步建议 - 如果您怀疑分配给您的一个后台作业的 PID 被重新分配,请在 ps 中检查它是否仍然是 您的 进程与 您的可执行文件并且具有 PPID(父 PID)1。

【讨论】:

    【解决方案3】:

    您不能“阻止”内核重用 PID。不过,我倾向于认为这对你来说不是问题。

    但考虑连续启动多个后台作业,然后等待它们全部完成。

    一个简单的wait(不带参数)将等待所有子进程完成。所以,你不必担心 PID 被重复使用。

    当您启动多个后台进程时,PID 确实有可能被其他进程重用。 但这不是问题,因为您不能在进程上wait,除非它是您的子进程。

    否则,检查您启动的后台作业之一是否通过wait 以外的任何方式完成总是不可靠的。

    【讨论】:

    • 更进一步,如果您尝试等待一个不是当前 shell 子进程的进程,wait 会打印一条错误消息并以状态 127 退出。这不会是正常进程的退出状态,让您可以区分其中一个子进程的错误和尝试等待进程 ID 可能在其他地方使用的已完成作业。
    • wait 有确切的问题。如果我启动 2 个后台进程,我不知道我应该以哪个顺序 wait 让它们完成。当我使用其他 PID 运行命令 wait 时,一个可能会完成!在这种情况下,已完成进程的 PID 可能会被重新使用。
    • 进程 ID 至少 16位;你真的担心你的机器在一个工作完成和另一个工作返回时调用wait之间的时间内产生 60,000 多个新进程吗?
    • 出现一个问题,如果我们想可靠地获取每个后台作业的错误代码,内核重用PID会导致问题。例如,睡眠 10 秒 & ===> X pidX=$!睡眠 5s & ===> Y pidY=$! wait pidX wait pidY Y 首先退出,假设另一个进程被加载到系统中,pid 与 pidY 相同。第二次等待它并等待抱怨:wait: pid pidY is not a child of this shell 对于这种情况,可靠的方法是让后台将返回码存储在一个文件中,并让父级从文件中获取它。
    【解决方案4】:

    除非您检索到子进程的返回值,否则它将存在于内核中。这也意味着它的 pid 已绑定到它,并且在此期间不能被重用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-05
      • 2019-01-04
      • 1970-01-01
      • 2012-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多