控制 Ctrl+C 取消哪个进程

Mat*_*hid 15 bash signals

我有一张可以启动到 Linux 并运行一个小的 Bash 脚本的 live CD。该脚本搜索并运行第二个程序(通常是编译后的 C++ 二进制文件)。

您应该能够通过按Ctrl+来中止第二个程序C。什么应该发生的是,第二个节目暂停,和bash脚本运行继续清理。什么实际发生的是主应用程序和bash脚本都终止。这是一个问题。

所以我使用trap内置命令告诉 Bash 忽略 SIGINT。现在Ctrl+C终止 C++ 应用程序,但 Bash 继续运行。伟大的。

哦,是的...有时“第二个应用程序”是另一个 Bash 脚本。在这种情况下,Ctrl+C现在什么都不做

显然我对这些东西如何工作的理解是错误的......当用户按下Ctrl+时,我如何控制哪个进程获得 SIGINT C?我想将此信号定向到一个特定的进程

Mat*_*hid 11

经过许多小时的互联网搜索,我找到了答案。

  1. Linux 有进程组的概念。

  2. TTY 驱动程序有一个前台进程组的概念。

  3. 当您按Ctrl+ 时C,TTY 会发送SIGINT到前台进程组中的每个进程。(另请参阅此博客条目。)

这就是编译后的二进制文件启动它的脚本都被破坏的原因。事实上,我只希望主应用程序接收这个信号,而不是启动脚本。

现在解决方案很明显:我们需要将应用程序放在一个新的进程组中,并使其成为此 TTY 的前台进程组。显然,这样做的命令是

setsid -c <applcation>
Run Code Online (Sandbox Code Playgroud)

这就是全部。现在,当用户按下Ctrl+ 时C, SIGINT 将被发送到应用程序(以及它可能拥有的任何孩子)而不是其他任何人。这就是我想要的。

  • setsid 它本身将应用程序放在一个新的进程组中(实际上,一个全新的“会话”,它显然是一组进程组)。

  • 添加-c标志使这个新进程组成为当前 TTY 的“前台”进程组。(即,SIGINT当你按下Ctrl+时它会得到C

我已经看到很多关于 Bash 何时在新进程组中运行或不运行进程的相互矛盾的信息。(特别是,对于“交互式”和“非交互式”shell,它似乎是不同的。)我已经看到一些建议,您可以将其与巧妙的管道技巧一起使用……我不知道。但是上面的方法似乎对我有用。

  • 你几乎明白了......运行脚本时默认禁用作业控制,但您可以使用`set -m`启用它。每次运行一个孩子时,它都比使用 `setsid` 更简洁、更简单。 (5认同)