在评论对这个答案的另一个问题,该评论说:
除非绝对必要,否则不要使用kill -9!SIGKILL无法被捕获,因此被杀死的程序无法运行任何关闭例程来例如擦除临时文件.首先尝试HUP(1),然后是INT(2),然后是QUIT(3)
我原则上同意SIGKILL
,但其余的对我来说都是新闻.鉴于发送的默认信号kill
是SIGTERM
,我预计它是任意进程正常关闭的最常见信号.此外,我已经看到SIGHUP
用于非终止原因,例如告诉守护程序"重新读取您的配置文件".而且在我看来SIGINT
(你通常用Ctrl-C得到的中断,对吗?)并没有得到应有的广泛支持,或者相当不合适地终止.
鉴于这SIGKILL
是最后的手段 - 您应该向任意进程发送哪些信号以及以何种顺序发送信号,以便尽可能优雅地关闭它?
如果可以,请用支持事实(超出个人偏好或意见)或参考资料证实您的答案.
注意:我对包括考虑bash/Cygwin的最佳实践特别感兴趣.
编辑:到目前为止,似乎没有人提到INT或QUIT,并且有限提及HUP.是否有任何理由将这些包括在有序的过程中?
SIGTERM告诉应用程序终止. 其他信号告诉应用程序其他与关闭无关但可能有相同结果的事情.不要使用那些.如果您希望关闭应用程序,请告诉它.不要给它误导信号.
有些人认为终止进程的智能标准方法是向其发送大量信号,例如HUP,INT,TERM,最后是KILL.这是荒唐的.终止的正确信号是SIGTERM,如果SIGTERM没有立即终止该过程,那么这是因为应用程序选择处理信号.这意味着它有一个很好的理由不立即终止:它有清理工作要做.如果你用其他信号中断清理工作,就不知道它还没有保存到磁盘中的内存中的哪些数据,哪些客户端应用程序处于挂起状态,或者你是否正在"中等句子"中断它,这实际上是数据损坏.
有关信号真正含义的更多信息,请参阅sigaction(2).不要将"默认操作"与"描述"混淆,它们不是一回事.
SIGINT用于表示进程的交互式"键盘中断".一些程序可以以特殊方式处理该情况以用于终端用户.
SIGHUP用于表示终端已消失且不再查看该过程.就这些.有些进程选择关闭响应,通常是因为没有终端它们的操作没有意义,有些选择执行其他操作,例如重新检查配置文件.
SIGKILL用于从内核强制删除进程.它在某种意义上是特殊的,它实际上并不是进程的信号,而是由内核直接解释.
不要发送SIGKILL. 肯定不会通过脚本发送SIGKILL.如果应用程序处理SIGTERM,它可能需要一秒钟来清理,它可能需要一分钟,可能需要一个小时.取决于应用程序在准备结束之前必须完成的工作.任何" 假定 "应用程序的清理序列的逻辑已经花了足够长的时间,并且需要在X秒之后是快捷方式或SIGKILLed,这是完全错误的.
应用程序需要 SIGKILL终止的唯一原因是,如果在清理序列期间出现问题.在这种情况下,您可以手动打开终端和SIGKILL.除此之外,唯一的其他原因,为什么你会SIGKILL东西是因为你WANT,以防止其自我整顿.
即使世界上一半的人在5秒后盲目地发送SIGKILL,但仍然是非常错误的事情.
简答:发送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
命令会发生什么?它会尝试SIGTERM
和SIGKILL
唯一的.为什么你认为是这样的?为什么你需要任何其他信号,如果这个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-run
的onliners.总是用它来测试.
脚本杀人
实际上我对这个问题很感兴趣,于是我决定创建一个小脚本来做到这一点.请随意下载(克隆)它:
GitHub链接到Killgracefully存储库
通常你发送SIGTERM
,默认为kill.这是默认的原因.只有当程序没有在合理的时间内关闭时才能使用SIGKILL
.但请注意,SIGKILL
该程序没有可能清理东西,数据可能会被破坏.
至于SIGHUP
,HUP
代表"挂断"并且历史意味着调制解调器断开连接.它基本上相当于SIGTERM
.守护进程有时SIGHUP
用来重新启动或重新加载配置的原因是守护进程从任何控制终端分离,因为守护进程不需要那些,因此永远不会接收SIGHUP
,因此信号被认为是"释放"用于一般用途.并非所有守护进程都使用它来重新加载!SIGHUP的默认操作是终止,许多守护进程表现如此!因此,你不能盲目地向SIGHUP
守护进程发送s并期望它们存活下来.
编辑: SIGINT
可能不适合终止进程,因为它通常与^C
终端设置或中断程序无关.许多程序都是为了自己的目的而捕获它,因此它不常用.SIGQUIT
通常默认情况下创建核心转储,除非你想要核心文件,否则它也不是一个好的候选者.
摘要:如果您发送SIGTERM
并且程序没有在您的时间范围内死亡,那么发送它SIGKILL
.
SIGTERM
实际上意味着向应用程序发送一条消息:" 你会这么善良并自杀 ".它可以被应用程序捕获和处理,以运行清理和关闭代码.
SIGKILL
不能被应用程序困住.应用程序被操作系统杀死而没有任何清理机会.
通常先发送SIGTERM
,睡一段时间然后发送SIGKILL
.