问题标签 [process-group]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
linux - 如何在自己的进程组中启动一个进程?
我想在它自己的进程组中启动一个进程(或者,一旦启动就改变它的组)并且:
- 让组中的进程从终端响应
Ctrl
+C
- 获取进程组的 id,以便我可以通过
kill
命令终止组中的所有进程。
注意:我尝试过setsid prog [args]
,但进程没有从终端响应 Ctrl+C,也无法获得新的进程组 ID。
我还尝试通过 Perl 的setpgrp($pid, $pid)
and更改进程组POSIX::setpgid($pid, $pid)
,但无济于事。
编辑:更大的问题:
我有一个进程(单线程;我们称其为“多产”进程P
),它同步启动许多子进程(一个接一个;当前一个子进程终止时,它会启动一个新进程)。从终端,我希望能够杀死P
它下面的进程树。为此,我可以简单地安排杀死P
's 组中的进程。但是,默认行为是P
在其父进程的组中。这意味着P
如果我杀死P
' 组中的所有进程,则 ' 的父级将被杀死,除非我有P
并且它的树在他们自己的组中。
我的意图是杀死P
它下面的树,而不是P
' 的父母。另外,我不能修改P
's 代码本身。
linux - 如何设置shell脚本的进程组
如何设置shell脚本的进程组?另外我希望所有子进程都在同一个进程组中
我期望类似于 C 中的 setpgid() 的东西。
c - Linux 是否允许将进程组 ID 重新分配给进程?
假设 pidX
是进程组的领导者并X
终止,但进程组中的其他进程仍在运行(以X
它们的 pgid 作为其 pgid)。Linux 会阻止将值X
作为 pid 分配给新进程吗?
我问这个是因为 POSIX 允许的故障条件setsid
:
[EPERM] 调用进程已经是进程组长,或者调用进程以外的进程组ID与调用进程的进程ID匹配。
对于使用“随机”触发的进程组(即 shell)的代码来说,这个错误似乎是一个不可恢复的条件,这使得它更加可恶。我会假设任何针对正常质量水平的实现都会避免X
在它仍用作 pgid 时重新分配为 pid,但我无法在任何地方找到此文档。
c - 将进程发送到后台并将控制权返回给我的 shell
我正在为我的 CS 类编写一个 shell,如果用户传入了“&”字符,则该项目的一部分涉及在后台运行一个进程。
如果一个进程在前台运行,我只是execvp
该进程,它仍然控制着终端,因为它在前台。但是,如果它是后台进程,我必须在开始执行该进程后将控制权返回给我的主 shell。我知道系统调用tcsetpgrp(pid_t)
将作为参数传入的进程放在前台,但我不太明白如何使用它。
如果它是后台进程,tcsetpgrp
我应该打电话吗?execvp
如果是这样,我可以通过调用来获取我的 shell 的 pidgetpid
吗?
c++ - 库的子进程的进程组
我正在开发一个将集成到客户端代码中的库(C++)。该库将产生一些子进程,并且必须监视它们以在它们死后立即重新生成它们(出于任何原因)。我需要使用 vfork 和 exec 来生成这些子进程。
我知道我必须使用信号处理程序来处理 SIGCHLD 并调用 waitpid 来检测哪个孩子已经死了。但是,用户代码可能使用相同的想法来处理自己的子进程。
如果我调用 waitpid,我将检索有关任何可能死亡的子进程的信息(我的或不是我的)。如果死亡过程是我的,没问题……幸福的情况。但是,如果是来自用户,他不会得到任何相关信息,因为我已经调用了 waitpid。
我该如何解决这个问题?
我的第一个想法是使用进程组。第一次分叉时,我会获取子 pid 并将其保存为进程组 ID。我创建的每个孩子,我都会将它的组设置为这个pid。大家觉得这样的选择好不好?(我遇到了麻烦)。
我的第二个想法是将信号处理程序重置为原始处理程序(或直接调用它)。如果我重新发出信号,原始处理程序将能够得到它。之后我必须重新安装我的信号处理程序。会是一个不错的选择吗?
我的第三个选择是使用 INFO(扩展信号处理程序)。我相信消亡过程的pid将在信息结构中可用。如果这是我的一个孩子,我会为此打电话给waitpid,没关系。如果那不是我的,我会调用原始信号处理程序。会是一个不错的选择吗?
最后一个问题。为了能够调用原始信号处理程序,我应该始终恢复它们并重新发出信号还是仅将其作为函数调用来调用就足够了?
非常感谢您的帮助。
linux - 如何在 Linux OS 中的一个进程组中获取 pid
我有一个关于 Linux pid 的问题。如何在同一组中获取pid?在 Linux 中使用 'ps' 命令获取所有 pid 或 pgid 似乎很容易,但是如何获取属于同一组的 pid,或者换句话说,如何获取同一个程序的 pid?有人请给我一些帮助吗?谢谢!
shell - 交互式 shell 应该在孤立的进程组中做什么?
简短的问题是,如果 shell 位于不拥有 tty 的孤立进程组中,它应该做什么?但我建议阅读长问题,因为它很有趣。
这是一种有趣且令人兴奋的方法,可以使用您最喜欢的外壳将您的笔记本电脑变成便携式空间加热器(除非您是那些 tcsh 怪人之一):
这会导致 bash 将 CPU 固定在 100%。zsh 和 fish 也一样,而 ksh 和 tcsh 咕哝着一些关于工作控制的事情,然后就倒下了,这有点好,但不多。哦,这是一个与平台无关的违规者:OS X 和 Linux 都受到影响。
我的(可能是错误的)解释如下:子外壳检测到它不在前台:tcgetpgrp(0) != getpgrp()
. 因此它试图停止自己:killpg(getpgrp(), SIGTTIN)
. 但是它的进程组是孤立的,因为它的父进程(C 程序)是领导者并死亡,并且发送到孤立进程组的 SIGTTIN 只是被丢弃(否则没有任何东西可以再次启动它)。因此,子 shell 并没有停止,但它仍然在后台,所以它会立即再次执行所有操作。冲洗并重复。
我的问题是,命令行 shell 如何检测到这种情况,它应该做什么?我的想法是外壳尝试read
从标准输入,如果读取给它 EIO 就退出。
谢谢你的想法!
编辑:我尝试在 /dev/tty 上执行零长度读取(),并且成功了,这很糟糕。为了获得 EIO,我实际上必须准备从 /dev/tty 读取一些数据。
编辑:我的另一个想法是kill(getpgrp(), 0)
。如果进程组是孤立的,那么我相信这将永远失败。但是,它也可能会失败,因为我无权向会话负责人发出信号。
编辑:对于以后发现此问题的任何人,我最终所做的都在https://github.com/fish-shell/fish-shell/issues/422中进行了描述。还有,未来怎么样?
linux - 生成外部程序时调用 setpgid/setsid
从我的代码运行外部程序时,我有以下三个选项:
- 之后什么都不做
fork()
。外部程序将在其父进程组中。 - 调用
setpgid(0, 0)
或类似的,因此外部程序将获得自己的进程组。 - Call
setsid()
,它还将外部程序与其父级的控制 tty 分开。
以上哪些行为在哪些情况下是正确的?
例如,我看到一个使用 vim 和 gnome-open 的有趣行为:
- 我运行
:!gnome-open somefile.pdf
,它启动 PDF 查看器并立即返回。 - 然后我运行,例如,,
:!cat
当 cat 运行时,发送一个SIGQUIT
usingCTRL-\
。
PDF 查看器崩溃。发生这种情况是因为 vim 和 gnome-open 似乎都在自己的进程组中生成了它们的子进程。
被称为 bug 可能太晦涩难懂,但我仍然想知道是谁的错:vim 或 gnome-open 是否有任何理由setpgid
在分叉后不调用,就像 shell 会做的那样?gnome-open
改为调用setsid
将 X 应用程序与其启动的终端分开是否更有意义?(我觉得奇怪的是 GLib 没有提供标准和跨平台的方式来做这些事情。)
linux - 在新会话中启动进程以便能够一次杀死所有树
有一个面向 Linux 的 Python 程序正在启动 Puppet 子进程。Puppet 是一个配置管理软件,在执行它时会启动许多子进程(yum、curl、自定义脚本等)。Python 代码有一个看门狗,如果 puppet 子进程运行时间过长,它会杀死它。在当前版本中,它使用 os.kill 来做到这一点。问题是,当 puppet 进程在超时时被终止时,它的孤儿会被附加到“init”并继续运行。通常,这些孩子是超时的初始原因。
第一次尝试是杀死整个进程组(os.killpg)。但是 kill 调用失败并出现 OSError(3, 'No such process')。在研究了流程管理文档后,我了解到它不起作用,因为 puppet 本身在一个单独的流程组中启动了 ruby 流程。此外,进程组不会被子进程继承,因此 os.killpg 无论如何也无济于事。是的,POSIX 允许设置具有某些限制的子进程的 PGID,但它需要对新子进程进行迭代监视,并且在我的情况下看起来像是 hack。
下一次尝试是在单独的外壳(“sh -c”)/“su”环境/setsid(以各种组合)中运行 Puppet。期望的结果是在新会话中启动此进程(和子进程)。我希望它将允许模拟远程 ssh 连接断开之类的东西:向会话负责人发送 SIGHUP,例如 puppet 进程,会将 SIGHUP 发送到整个子树。所以我将能够杀死整棵树。通过远程 SSH 连接运行 puppet 的实验表明,这种方法似乎有效:所有进程在终端断开连接后都会死掉。我还没有从 Python 实现这种行为。这种方法是否正确,我是否遗漏了什么或者它是一个丑陋的黑客?
我看到的另一种方法是将 SIGSTOP 发送到树中的每个进程(在树中至少有一个正在运行的进程时进行迭代以避免竞争条件),然后单独杀死每个进程。这种方法可行,但看起来不太优雅。
问题与 Python 代码无关,它还会在从控制台运行“puppet apply”并使用“kill”命令发送信号时重现。
是的,我知道 Puppet 有一个用于所述目的的“超时”关键字,但我正在寻找一个更通用的解决方案,不仅适用于 Puppet,而且适用于任何富有成效的子流程。
c - SIGTERM 给所有子进程,但不是父进程
我有一个通过响应信号来运行的 C 程序。一些信号会导致父节点分叉。这允许在父进程继续响应信号时进行其他处理。
当父母收到一个 SIGTERM 时,我希望分叉的孩子也收到一个 SIGTERM。孩子在父母退出之前完成处理 SIGTERM 并不重要。
kill(0, SIGTERM)
但是,使用下面的代码,当我从父母那里打电话时,孩子们不会收到 SIGTERM 。从kill
manpage看来,所有孩子都应该得到这个 SIGTERM。
我为父级设置了信号处理程序。
在获得需要分叉的信号后,我执行以下操作
在do_fork_stuff
中,孩子睡了 30 秒。然后我打电话kill(0, SIGTERM)
给家长。孩子们不会终止。
孩子们没有得到 SIGTERM 的原因是什么?