当前位置:  开发笔记 > 编程语言 > 正文

我应该以什么顺序发送信号以正常关闭进程?

如何解决《我应该以什么顺序发送信号以正常关闭进程?》经验,为你挑选了4个好方法。

评论对这个答案的另一个问题,该评论说:

除非绝对必要,否则不要使用kill -9!SIGKILL无法被捕获,因此被杀死的程序无法运行任何关闭例程来例如擦除临时文件.首先尝试HUP(1),然后是INT(2),然后是QUIT(3)

我原则上同意SIGKILL,但其余的对我来说都是新闻.鉴于发送的默认信号killSIGTERM,我预计它是任意进程正常关闭的最常见信号.此外,我已经看到SIGHUP用于非终止原因,例如告诉守护程序"重新读取您的配置文件".而且在我看来SIGINT(你通常用Ctrl-C得到的中断,对吗?)并没有得到应有的广泛支持,或者相当不合适地终止.

鉴于这SIGKILL是最后的手段 - 您应该向任意进程发送哪些信号以及以何种顺序发送信号,以便尽可能优雅地关闭它?

如果可以,请用支持事实(超出个人偏好或意见)或参考资料证实您的答案.

注意:我对包括考虑bash/Cygwin的最佳实践特别感兴趣.

编辑:到目前为止,似乎没有人提到INT或QUIT,并且有限提及HUP.是否有任何理由将这些包括在有序的过程中?



1> lhunath..:

SIGTERM告诉应用程序终止. 其他信号告诉应用程序其他与关闭无关但可能有相同结果的事情.不要使用那些.如果您希望关闭应用程序,请告诉它.不要给它误导信号.

有些人认为终止进程的智能标准方法是向其发送大量信号,例如HUP,INT,TERM,最后是KILL.这是荒唐的.终止的正确信号是SIGTERM,如果SIGTERM没有立即终止该过程,那么这是因为应用程序选择处理信号.这意味着它有一个很好的理由不立即终止:它有清理工作要做.如果你用其他信号中断清理工作,就不知道它还没有保存到磁盘中的内存中的哪些数据,哪些客户端应用程序处于挂起状态,或者你是否正在"中等句子"中断它,这实际上是数据损坏.

有关信号真正含义的更多信息,请参阅sigaction(2).不要将"默认操作"与"描述"混淆,它们不是一回事.

SIGINT用于表示进程的交互式"键盘中断".一些程序可以以特殊方式处理该情况以用于终端用户.

SIGHUP用于表示终端已消失且不再查看该过程.就这些.有些进程选择关闭响应,通常是因为没有终端它们的操作没有意义,有些选择执行其他操作,例如重新检查配置文件.

SIGKILL用于从内核强制删除进程.它在某种意义上是特殊的,它实际上并不是进程的信号,而是由内核直接解释.

不要发送SIGKILL. 肯定不会通过脚本发送SIGKILL.如果应用程序处理SIGTERM,它可能需要一秒钟来清理,它可能需要一分钟,可能需要一个小时.取决于应用程序在准备结束之前必须完成的工作.任何" 假定 "应用程序的清理序列的逻辑已经花了足够长的时间,并且需要在X秒之后是快捷方式或SIGKILLed,这是完全错误的.

应用程序需要 SIGKILL终止的唯一原因是,如果在清理序列期间出现问题.在这种情况下,您可以手动打开终端和SIGKILL.除此之外,唯一的其他原因,为什么你会SIGKILL东西是因为你WANT,以防止其自我整顿.

即使世界上一半的人在5秒后盲目地发送SIGKILL,但仍然是非常错误的事情.


你是对的,那里有很多滥用SIGKILL的东西.但是有一个时间和地点可以使用它,即使是从脚本中也是如此.很多很多应用程序都会陷入SIGTERM并在不到一秒的时间内或在几秒钟内正常退出,其中一个仍在30秒之后运行,因为它已被楔入.
*不要发送SIGKILL.永远.简直就是错误.*真的吗?由于无限循环,即使您的系统已经烧毁了.祝好运.-1
@dwc:尝试让它运行一次一小时.如果它没有死,那么它就会"楔入"并修复它,或者是懒惰的,并且在将来SIGKILL它之后.*注意*你可能会腐败的东西,并记住,这不是你应该做的"默认情况下".

2> Dr Beco..:

简答:发送SIGTERM,30秒后,SIGKILL.也就是说,发送SIGTERM,等待一下(它可能因程序而异,你可能会更好地了解你的系统,但是5到30秒就足够了.当关闭一台机器时,你可能会看到它自动等待1到30秒.为什么匆忙,毕竟?),然后发送SIGKILL.

合理的答案:SIGTERM,SIGINT,SIGKILL 这是绰绰有余.这个过程可能会在此之前终止SIGKILL.

长的答案:SIGTERM,SIGINT,SIGQUIT,SIGABRT,SIGKILL

这是不必要的,但至少你不会误导有关你的消息的过程.所有这些信号确实意味着您希望流程停止正在执行的操作并退出.

无论您从这个解释中选择什么答案,请记住这一点!

如果您发送的信号意味着其他内容,则该过程可能会以非常不同的方式处理(一方面).另一方面,如果进程没有处理信号,那么你发送的内容并不重要,无论如何都会退出进程(当然,当默认动作终止时).

所以,你必须像自己一样思考程序员.你会编写一个函数处理程序,比如说,SIGHUP退出一个与某个东西连接的程序,或者你是否会循环它以尝试再次连接?这是主要问题!这就是为什么发送意味着你想要的信号很重要的原因.

几乎是愚蠢的答案:

下表包含相关信号,以及程序未处理时的默认操作.

我按照我建议使用的顺序订购了它们(顺便说一下,我建议你使用合理的答案,而不是这里的这个),如果你真的需要全部尝试它们(说这个表是按顺序排列会很有趣他们可能造成的破坏,但这并非完全正确).

建议使用带星号(*)的信号.关于这些的重要一点是你可能永远不知道它的编程是做什么的.特别SIGUSR!它可以启动apocalipse(这是程序员做任何他/她想做的免费信号!).但是,如果没有处理OR,在不太可能的情况下处理终止,程序将终止.

在表中,具有默认选项以终止和生成核心转储的信号将保留在最后,就在之前SIGKILL.

Signal     Value     Action   Comment
----------------------------------------------------------------------
SIGTERM      15       Term    Termination signal
SIGINT        2       Term    Famous CONTROL+C interrupt from keyboard
SIGHUP        1       Term    Disconnected terminal or parent died
SIGPIPE      13       Term    Broken pipe
SIGALRM(*)   14       Term    Timer signal from alarm
SIGUSR2(*)   12       Term    User-defined signal 2
SIGUSR1(*)   10       Term    User-defined signal 1
SIGQUIT       3       Core    CONTRL+\ or quit from keyboard
SIGABRT       6       Core    Abort signal from abort(3)
SIGSEGV      11       Core    Invalid memory reference
SIGILL        4       Core    Illegal Instruction
SIGFPE        8       Core    Floating point exception
SIGKILL       9       Term    Kill signal

那么我会建议这几乎是愚蠢长的答案: SIGTERM,SIGINT,SIGHUP,SIGPIPE,SIGQUIT,SIGABRT,SIGKILL

最后,

绝对愚蠢的长龙答案:

不要在家尝试这个.

SIGTERM,SIGINT,SIGHUP,SIGPIPE,SIGALRM,SIGUSR2,SIGUSR1,SIGQUIT,SIGABRT,SIGSEGV,SIGILL,SIGFPE如果没有什么工作,SIGKILL.

SIGUSR2之前应该尝试,SIGUSR1因为如果程序不处理信号,我们会更好.SIGUSR1如果它只处理其中一个,它更有可能处理它.

BTW,KILL:发送SIGKILL到流程并没有错,正如其他答案所述.那么,想想发送shutdown命令会发生什么?它会尝试SIGTERMSIGKILL唯一的.为什么你认为是这样的?为什么你需要任何其他信号,如果这个shutdown命令只使用这两个?


现在,回到长期答案,这是一个很好的oneliner:

for SIG in 15 2 3 6 9 ; do echo $SIG ; echo kill -$SIG $PID || break ; sleep 30 ; done

它在信号之间休眠30秒.为什么还需要一个oneliner?;)

此外,建议:只15 2 9使用合理答案的信号进行尝试.

安全:echo准备好时取下第二个.我把它称为我dry-runonliners.总是用它来测试.


脚本杀人

实际上我对这个问题很感兴趣,于是我决定创建一个小脚本来做到这一点.请随意下载(克隆)它:

GitHub链接到Killgracefully存储库



3> dwc..:

通常你发送SIGTERM,默认为kill.这是默认的原因.只有当程序没有在合理的时间内关闭时才能使用SIGKILL.但请注意,SIGKILL该程序没有可能清理东西,数据可能会被破坏.

至于SIGHUP,HUP代表"挂断"并且历史意味着调制解调器断开连接.它基本上相当于SIGTERM.守护进程有时SIGHUP用来重新启动或重新加载配置的原因是守护进程从任何控制终端分离,因为守护进程不需要那些,因此永远不会接收SIGHUP,因此信号被认为是"释放"用于一般用途.并非所有守护进程都使用它来重新加载!SIGHUP的默认操作是终止,许多守护进程表现如此!因此,你不能盲目地向SIGHUP守护进程发送s并期望它们存活下来.

编辑: SIGINT可能不适合终止进程,因为它通常与^C终端设置或中断程序无关.许多程序都是为了自己的目的而捕获它,因此它不常用.SIGQUIT通常默认情况下创建核心转储,除非你想要核心文件,否则它也不是一个好的候选者.

摘要:如果您发送SIGTERM并且程序没有在您的时间范围内死亡,那么发送它SIGKILL.


请注意,只有在立即关闭比防止数据丢失/数据损坏更高的优先级的情况下,才应该使用SIGKILL.
@Jack让我试试:SIGHUP是"挂机"信号,告诉进程终端断开连接.由于守护进程在后台运行,因此它们不需要终端.这意味着"挂断"信号与守护进程无关.它们永远不会从终端断开接收它,因为它们首先没有连接终端.而且由于无论如何都定义了信号,尽管它们不需要它用于原始目的,但是许多守护进程使用它来代替不同的目的,例如重新读取它们的配置文件.

4> vartec..:

SIGTERM实际上意味着向应用程序发送一条消息:" 你会这么善良并自杀 ".它可以被应用程序捕获和处理,以运行清理和关闭代码.

SIGKILL不能被应用程序困住.应用程序被操作系统杀死而没有任何清理机会.

通常先发送SIGTERM,睡一段时间然后发送SIGKILL.

推荐阅读
php
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有