金德勒/温柔/微妙的替代品killall(例如“ endall”)?


17

如何以比平时更温和的方式结束所有具有相同名称的进程killall?我不想中断这些过程,但给他们留出适当的时间退出。


也可以看看:

如何在Ubuntu中终止进程?

在系统监视器中,终止进程和结束进程有什么区别?

为什么killall(有时?)需要应用两次?

tl; dr


1
你的问题是?
飞行员

@ Pilot6 重新措辞:什么是killall的“更软”替代方案?
关于natty的坚果,2015年

1
什么是“较软”?
飞行员

Answers:


43

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

killall默认情况下发送SIGTERM。这已经是一种不错的方法,它使应用程序有机会自行清理。“现在已经死了!” 方法是发送SIGKILL信号,这需要将其指定为的选项killall。来自GNU C库:终止信号

巨集:int SIGTERM

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


2. System Monitor的“结束进程”同样好(SIGTERM也是如此)

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

data / 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>

这里的15是信号编号。信号15为SIGTERMSIGTERM在询问和回答其他问题之前,System Monitor已经使用了很长时间。


技术附录(回应评论)

查看的Github表示形式git blame,这是对GNOME System Monitor的源代码中的信号拼写方式进行的更改:

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

这些都没有从更改SIGQUITSIGTERM,最后一个是在提出链接问题之前。


7
+1表示源代码!(+2代表与“常规智慧”相抵触;)
含糊不清的内容2015年

好吧,在说明您与答案矛盾之前,您是否检查了所有版本的源代码都使用了15?它可能已在某些时候进行了更改,因此旧答案相对于旧版本可能是100%正确。
Bakuriu

1
@Bakuriu我确实以相反的方式与该答案相矛盾,但是很公平,我会尽力记住下次检查是否可以。
hvd

源git树中的@Bakuriu git grep 'SIGQUIT'没有显示任何内容。均未发现与信号相关的任何东西git grep '>3<'。我得出结论,最有可能的gnome-system-monitor从未使用过SIGQUIT
Ruslan 2015年

@Ruslan git grep仅搜索当前树,而不搜索整个历史记录。我使用了git blame(实际上是与Github相当的工具)来进行更深入的挖掘,但仍然没有任何结果。
hvd

5

@hvd的答案基本上是正确的。为了进一步备份该文件,init进程将SIGTERM在关闭计算机时首先发送到进程,然后在SIGKILL尚未退出的情况下发送延迟。进程无法处理/忽略SIGKILL

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

换句话说,根据其他答案,如果您有一个由@Jos或@AlexGreg编写的程序,则它们可能正在处理SIGQUIT但可能没有处理SIGTERM,因此发送的SIGTERM“软性”不如SIGQUIT

我已经编写了一些代码,因此您可以自己使用它。将以下内容另存为signal-test.c,然后使用

gcc -o signal-test signal-test.c

然后可以运行它./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;
}

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

$ ./signal-test
Terminated

$ ./signal-test
Quit (core dumped)

$ ./signal-test
flag is 15

$ ./signal-test
flag is 3

取决于您是否处理信号。

您也可以尝试忽略信号:

signal(SIGTERM, SIG_IGN);

如果这样做,那么发送SIGTERM将无济于事,您将不得不使用它SIGKILL来结束该过程。

中的更多详细信息man 7 signal。请注意,signal()以这种方式使用被认为是不可携带的-尽管比其他方式容易得多!

另一个较小的脚注-在Solaris上killall试图杀死所有进程。他们全部。如果您以root身份运行,则可能会感到惊讶:)


1
这是我偏爱的原因之一pkill。另一个原因是它与配对pgrep,这使得更容易准确地检查将杀死哪些进程,并且哪个本身具有比更好的匹配语义ps | grep
2015年

1

“全部结束”将是killall -s SIGQUIT [process name]。如果您想要一个理想的解决方案,请定义alias endall='killall -s SIGQUIT'


13
SIGQUIT就像制作流程一样abort(3):先转储核心,然后终止流程。这绝对不比SIGTERM的默认值更好/更温顺/更亲民killall
Ruslan 2015年

3
对于处理信号的过程,SIGQUIT(甚至更好SIGINT)可以比对待“软”的处理SIGTERM,但这取决于应用程序。未经处理,它们中的任何一个都会立即终止。
R .. GitHub停止帮助ICE 2015年

1
如果您希望清理磁盘上的核心文件,这是一个好主意。
Nate Eldredge

2
@Qix:每个信号都会有所不同的一件事是,它是否会根据默认操作(如果未由应用程序处理)创建核心文件。使用不生成核心文件的信号可能更可取。
R .. GitHub停止帮助ICE 2015年

1
值得注意的是,ubuntu默认将核心文件大小限制设置为0,因此,除非您修改限制,否则SIGQUIT实际上不会生成核心文件(如果未处理)。
罗杰·莱特
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.