hvd*_*hvd 44

1. `killall` 已经很好了 (SIGTERM)

killall默认发送SIGTERM. 这已经是让应用程序有机会自行清理的好方法。“去死吧,马上!” 方法是发送一个SIGKILL信号,这需要将其指定为 的选项killall。来自GNU C 库:终止信号

宏:int SIGTERM

[...] 这是礼貌地要求程序终止的正常方式。


2. 系统监视器的“结束进程”同样好(SIGTERM,也是)

您链接到有关 GNOME 系统监视器的问题。这也SIGTERM用于其“结束流程”操作(我意识到我与该问题的答案相矛盾)。您可以在源代码中找到它来验证自己:

数据/menus.ui

<item>
  <attribute name="label" translatable="yes">_End</attribute>
  <attribute name="action">win.send-signal-end</attribute>
  <attribute name="accel">&lt;Primary&gt;e</attribute>
  <attribute name="target" type="i">15</attribute>
</item>
Run Code Online (Sandbox Code Playgroud)

这里的 15 是信号编号。信号 15 是SIGTERMSIGTERM在其他问题被提出和回答之前,系统监视器已经使用得很好。


技术附录(回应评论)

查看 的 Github 表示git blame,这里是对信号在 GNOME 系统监视器源代码中的拼写方式所做的更改:

383007f2 2013 年 7 月 24 日用 GAction 参数
0e766b2d替换了发送信号的重复代码2013 年 7 月 18 日将进程弹出菜单移植到 GAction
97674c79 2012 年 10 月 3 日摆脱 ProcData 结构
38c5296c 2011 年 7 月 3 日使源文件统一。

这些都没有从SIGQUIT变为SIGTERM,最后一个是在提出链接问题之前。

  • +1 用于参考源代码!(+2 表示与“传统智慧”相矛盾;) (7认同)

Rog*_*ght 5

@hvd 的回答基本正确。为了进一步支持,该init进程将首先SIGTERM在您关闭计算机时发送到进程,然后在延迟后发送(SIGKILL如果它们尚未退出)。进程无法处理/忽略SIGKILL.

不过,要提供更多细节,真正的答案是您无法确定程序会处理它。SIGTERM是最常用的信号,用于礼貌地要求程序退出,但所有信号处理都取决于程序对信号进行的操作。

换句话说,根据其他答案,如果您有一个由 @Jos 或 @AlexGreg 编写的程序,那么它们可能会处理SIGQUIT但可能不会处理SIGTERM,因此发送SIGTERM将比SIGQUIT.

我已经写了一些代码,所以你可以自己玩。将下面的另存为signal-test.c,然后编译

gcc -o signal-test signal-test.c
Run Code Online (Sandbox Code Playgroud)

然后你可以运行它./signal-test,看看当你发送不同的信号时会发生什么killall -s <signal>

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

int flag = 0;

void handle_signal(int s)
{
    flag = s;
}

int main(int argc, char *argv[])
{
    signal(SIGTERM, handle_signal);
    signal(SIGQUIT, handle_signal);

    while(flag == 0){
        sleep(1);
    }
    printf("flag is %d\n", flag);
    return flag;
}
Run Code Online (Sandbox Code Playgroud)

就目前而言,代码优雅地处理了 SIGTERM 和 SIGQUIT。您可以尝试注释掉这些行signal(SIG...//在行首使用 a )以删除信号处理程序,然后再次运行并发送信号。您应该能够看到这些不同的输出:

$ ./signal-test
Terminated

$ ./signal-test
Quit (core dumped)

$ ./signal-test
flag is 15

$ ./signal-test
flag is 3
Run Code Online (Sandbox Code Playgroud)

取决于您是否处理信号。

您也可以尝试忽略信号:

signal(SIGTERM, SIG_IGN);
Run Code Online (Sandbox Code Playgroud)

如果你这样做,那么发送SIGTERM将什么也不做,你将不得不使用SIGKILL来结束这个过程。

中的更多详细信息man 7 signal。请注意,signal()以这种方式使用被认为是不可移植的——尽管它比替代方法容易得多!

另一个小脚注 - 关于 Solariskillall试图杀死所有进程。他们都。如果您以 root 身份运行它,那么您可能会感到惊讶:)