我需要什么信息来确保杀死相同的进程,而不是很久以后用相同的 PID 生成的进程?

Mar*_*arc 22 process kill

我有一堆以start.sh脚本开头的命令,存储它们的 PID。然后,我想stop.sh在用户方便的时候通过运行来阻止它们。

注意陷阱:

  1. 我今天运行,它将 PID 、 、存储start.sh在文件中。150001500115002
  2. 我忘记停止我的进程。一周后,我重新启动了计算机。
  3. stop.sh现在运行脚本。15000它尝试终止具有 PID 、15001、的任务15002,不考虑文件而读取它们。
    => 这些任务,如果某些任务碰巧在我重新启动的新系统上具有这些 PID,则不再是我通过start.sh脚本启动的任务,并且我会将我的系统置于未知状态。

当我在 Linux 脚本中首先捕获进程的 PID 时$$,如何收集其他信息以确保我不会与将来可能出现的具有相同 PID 的另一个任务混淆?

例如,收集 PPID,或开始日期/时间,或确保某种“通用唯一性”的东西,如果我可以写这个..?

如何收集进程信息以及如何在不混乱的情况下杀死它?

Aus*_*arn 40

\n

如何收集进程信息以及如何在不混乱的情况下杀死它?

\n
\n

你不\xe2\x80\x99t。

\n

相反,您可以确保该流程在您稍后可以可靠地引用以再次找到它的上下文中运行。

\n

处理这个问题的正确方法是使用目标平台\xe2\x80\x99s服务管理系统(现在通常在Linux系统上使用systemd)。它们在大多数情况下都能正确处理事情,并且是专门为执行此类事情而设计的。

\n

按优先顺序降序排列的替代方案是:

\n
    \n
  • 使用具有特定名称的cgroup 。这种方法是特定于 Linux 的,但具有许多明显的好处,例如能够可靠且原子地杀死您启动的进程的所有子进程。它们本质上解决了生命周期问题,因为特定进程与 cgroup 显式关联,而不是 PID 与 cgroup 关联。
  • \n
  • 使用管理程序系统,例如runits6daemontools。这些解决方案通过利用一个可以轻松可靠地定位的进程作为您要监视的进程的父进程来解决该问题。
  • \n
  • 将您的 PID 文件放入/run应在的位置。您指出的跨系统重新启动的 PID 重用问题是一个已知问题,几十年来,通过简单地将 PID 文件放在每次系统重新启动时都会被擦除的目录中,\xe2\x80\x99s 已得到可靠解决。/run是 Linux 系统上的标准位置。这仍然存在 PID 重用问题(因为 PID 仅在关联进程的生命周期内是唯一的,因此其中一个进程意外终止并留下 PID 文件可能仍会遇到重用问题)。
  • \n
\n

  • 我认为你有最明智的答案,但在迫切需要的情况下,了解其他解决方案很有趣。 (2认同)

Pau*_*ant 12

当我必须在大型网络上启动各种诊断脚本时,我让所有脚本接受(并忽略)一个--tag=....选项。(显然,您不能使用标准命令来执行此操作,但您可以将它们包装在父 shell 中)。

典型的 --tag 将包含(至少)启动它的主机名、随机数和启动时间(精确到纳秒)。对于远程任务,您甚至可能不知道远程系统上的 pid。

ps命令可以显示参数,以便您可以 grep 特定进程。您甚至可以有一个 cron 作业,定期生成潜在进程的报告,并从列表中清除那些已终止的进程。


小智 11

将PID信息存储在tmpfs文件系统上,因此重新启动后,这些文件不存在。

/run通常是 tmpfs,或者/tmp在某些发行版上是 tmpfs。

或安装您自己的

# mount tmpfs /path/to/your/mountpoint -t tmpfs 
Run Code Online (Sandbox Code Playgroud)

  • 这还不够,因为即使不重新启动系统,PID 也可以重复使用。PID 可以重复使用。该问题特别指出,要求是为了避免“与将来可能出现的同一 pid 的另一个任务混淆”;这种方法没有实现这一点。 (7认同)
  • 也许它无法防止的一件事是,如果处理崩溃并且文件仍然存在。 (2认同)

ilk*_*chu 10

您可以收集有关进程的其他信息,但严格来说,很难绝对确定要杀死的进程与您认为的进程相同。

即使不考虑重新启动,也有可能在您终止进程之前,它会因不相关的原因而终止,而另一个进程会在正确的时间启动以再次获得相同的 PID。任何检查仍然是活跃的,因为在检查和发送终止信号之间该进程可能被另一个进程替换。

但是,如果您小心地在不用于其他用途的 UID 下启动进程,并从具有相同 UID(而不是 root)的进程发送终止信号,您就会知道您不会成功杀死任何东西别的。(PID 仍然可以被一些不相关的进程重用,那么你就无法杀死新的进程。)

如果确实要检查进程是否相同(并且可以忽略竞争的机会),那么您可能至少应该检查要杀死的进程的进程名称/完整命令行。例如,运行类似pgrep somecmd, 或 的pgrep -f 'somecmd with some args'命令来查找具有给定名称/命令行的进程,并查看您的 PID 是否在输出中列出。


Jos*_*ica 9

将 start.sh 绑定安装/proc/15000到某个其他目录。(最好这由父进程在退出之前完成,wait以避免竞争条件。)在 stop.sh 中,尝试打开您绑定安装的目录。如果绑定安装消失,则系统将重新启动。如果打开目录失败并显示 ESRCH(无此类进程),则进程退出。(即使此后具有相同 PID 的新进程开始运行,也会发生这种情况。)如果打开目录成功并且绑定安装仍然存在,那么它仍然是您的进程并且可以安全地终止。(为了避免另一个竞争条件,最好pidfd_send_signal杀死它。)


Dav*_*idT 6

您还需要处理 PID 翻转 - 我相信 Linux 上的默认值是 32768 - 因此,如果您执行足够多的进程,下一个进程将会翻转。

注意:翻转会绕过任何已存在的进程,例如 (PID 1) init。

但是,如果您同时存储进程的 PID 和启动时间,那么这应该足以在这台计算机上唯一地标识该进程。

如果您需要跨机器的唯一性,您还需要存储唯一标识机器的内容。

  • 你正确的32768仍然是32位系统上的默认值,但64位系统上的默认值是2^22 (3认同)