我想在单个 shell 上运行多个命令(进程)。都有自己的连续输出,不停歇。在后台运行它们Ctrl- C。我想将它们作为单个进程(子shell,也许?)运行,以便能够用Ctrl-停止所有这些进程C。
具体来说,我想使用mocha(监视模式)运行单元测试,运行服务器并运行一些文件预处理(监视模式),并在一个终端窗口中查看每个测试的输出。基本上我想避免使用一些任务运行器。
我可以通过在后台运行进程 ( &)来实现它,但是我必须将它们放到前台来阻止它们。我想要一个包装它们的过程,当我停止这个过程时,它会停止它的“孩子”。
在man page,它说:
kill [ -s signal | -p ] [ -a ] [ -- ] pid ...
pid... Specify the list of processes that kill should signal. Each pid can be one of five things:
0 All processes in the current process group are signaled
Run Code Online (Sandbox Code Playgroud)
我在 bash 中尝试这样:
$ man kill &
[1] 15247
$
[1]+ Stopped man kill
$ kill 0
$ ps
15247 pts/41 00:00:00 man
Run Code Online (Sandbox Code Playgroud)
这里0用作pid. 据我了解,kill 0将杀死当前进程中的所有进程,其中包括pid15247 …
在“ /sf/ask/912670041/ ”中,我看到所有答案都提到了ps,没有提到/proc。
“ps”似乎不是很便携(Android 和 Busybox 版本需要不同的参数),我希望能够使用简单且便携的工具列出带有 pgid 的 pid。
在 /proc/.../status 我看到Tgid:(线程组 ID),Gid:(组 ID 用于安全,而不是用于将进程分组在一起),但不是PGid:...
ps从 pid 获取 pgid 的其他(不使用)方法是什么?
所以我到处都在读这个命令应该终止父进程的所有子进程:
kill -- -$$
Run Code Online (Sandbox Code Playgroud)
在 kill 命令中使用负 ID 会引用一个 PGID,并且从我看到的示例来看,子进程的 PGID 应该是父进程的 PID,但在我的系统中并非如此。
在我的系统上,子脚本的 PGID 与父脚本的 PGID 相同,结果是 bash。
这里发生了什么?示例是错误的还是我的系统设置不同?
我需要实现的是在不终止父进程的情况下终止子进程,因此我不想向父进程所在的 PGID 发送终止信号。
我读到会话的 ID 与通过setsid()系统调用创建会话的进程的 pid 相同,但我没有找到有关如何设置进程组 ID 的任何信息。进程组 ID 是否与创建进程组的进程的 pid 相同?
(Re-posting in unix per the suggestion in /sf/ask/960287611/)
The short question is, what should a shell do if it is in an orphaned process group that doesn't own the tty? But I recommend reading the long question because it's amusing.
Here is a fun and exciting way to turn your laptop into a portable space heater, using your favorite shell (unless you're one of those tcsh weirdos):
#include <unistd.h>
int main(void) {
if (fork() == 0) {
execl("/bin/bash", "/bin/bash", …Run Code Online (Sandbox Code Playgroud) 进程组和作业有什么区别?如果我输入,pr * | lpr那么它既是进程组又是工作?进程组 ID 和作业 ID 之间究竟有什么区别?
编辑:我知道它看起来类似于工作和流程之间的区别是什么?,但略有不同。另外,我没有从这个线程中理解这个概念。
我想从另一个 bash 脚本启动一个 bash 脚本,但在它自己的进程组中启动它,就像从终端运行它一样。
有几个类似的问题,但我找不到与我的示例相匹配的答案。
拿这两个脚本
$ cat main.sh
#! /usr/bin/env bash
set -e
echo if this has been started in its own group the following will pass
ps -o ppid,pgid,command $$
ps -o pgid | grep $$
echo passed
$ cat wrapper.sh
#! /usr/bin/env bash
set -e
./main.sh
Run Code Online (Sandbox Code Playgroud)
当我main.sh单独运行时,终端将其放入自己的组中:
$ ./main.sh
if this has been started in its own group the following will pass
PPID PGID COMMAND
20553 1276 bash ./main.sh
1276
1276
1276
passed
$ …Run Code Online (Sandbox Code Playgroud) 在 POSIX 中,进程通过两个基本层次结构相互“关联”:
父进程和子进程的层次结构。
会话和进程组的层次结构。
用户进程通过setpgid和对后者有很大的控制权setsid,但他们对前者的控制很少——父进程 ID 在进程生成时设置,并在父进程退出时由内核更改(通常为 PID 1 ),否则它不会改变。回想起来,我一直在想亲子关系到底有多重要。
总结一下我目前的理解:
从父进程的角度来看,父子关系显然很重要,因为各种系统调用,如wait和setpgid,只允许在子进程中使用。
会话-组-进程关系显然对所有进程都很重要,包括会话领导者和会话中的其他进程,因为像kill对整个进程组进行操作的系统调用setpgid只能用于在同一会话中加入一个组,并且所有进程SIGHUP如果会话领导者退出,会话的前台进程组中的消息将被发送。
更重要的是,从父级的角度来看,这两个层次结构显然是相关的,因为setsid只影响新的子级,setpgid只能用于子级,但从子级的角度来看它们似乎基本无关(因为父进程死亡没有任何影响)在进程的组或会话上)。
然而,显然没有任何理由让子进程关心它的当前父进程是什么。因此,我有以下问题:从子进程的角度来看,的当前值是否getppid()有任何重要性,除了可能确定其生成过程是否已退出?
换一种方式提出同样的问题,假设同一个程序以两种不同的方式从同一个父级产生两次:
第一个孩子以通常的方式产生,fork()紧接着是exec().
第二个子进程是间接产生的:父进程调用fork(),然后子进程也调用fork(),而孙子进程调用exec()。然后直接子进程退出,因此孙子进程成为孤儿,它的 PPID 被重新分配给 PID 1。
在这个假设场景中,假设所有其他条件都相同,是否有任何合理的程序有理由做出不同的行为?到目前为止,我的结论似乎是“不”,因为会话保持不变,进程继承的文件描述符也是如此……但我不确定。
注意:我不认为“获取父 PID 与其通信”是该问题的有效答案,因为孤立程序通常不能依赖于将其 PPID 设置为 1(某些系统将孤立进程的 PPID 设置为某些其他值),因此避免竞争条件的唯一方法是getpid() 在分叉之前 …
kill -TERM -PID
Run Code Online (Sandbox Code Playgroud)
应该杀死PID及其所有子进程。
但这在 openSUSE 上不起作用,它总是告诉我没有这样的进程 -PID,无论我使用什么 PID。
因此,如果此特定版本的 kill 不支持负 PID 选项,那么杀死一组进程的最佳方法是什么?
背景:
我有一个 shell 脚本正在运行。在脚本中,我使用 wget 下载东西。所以脚本是父进程,wget 是子进程。我想使用 kill -TERM -PID_OF_SCRIPT 杀死它们
process ×10
process-groups ×10
bash ×2
kill ×2
shell-script ×2
command-line ×1
job-control ×1
linux ×1
posix ×1
proc ×1
shell ×1
signals ×1
tty ×1