在另一位comment的this answer question上,评论者说:
除非绝对,否则不要使用kill -9 必要! SIGKILL不能被困 被杀死的程序无法运行任何 例如关闭例程抹去 临时文件。首先尝试HUP(1), 然后是INT(2),然后是QUIT(3)
我原则上同意SIGKILL
,但其余的对我来说都是新闻。鉴于kill
发送的默认信号是SIGTERM
,我认为这是任意进程正常关闭的最常见信号。此外,我已经看到SIGHUP
用于非终止原因,例如告诉守护程序“重新读取您的配置文件”。而且在我看来SIGINT
(你通常用Ctrl-C得到的中断,对吗?)并没有得到应有的广泛支持,或者相当不理想地终止。
鉴于SIGKILL
是最后的手段 - 您应该向任意进程发送哪些信号以及按什么顺序,以便尽可能优雅地关闭它? / p>
如果可以,请用支持事实(超出个人喜好或意见)或参考资料来证实您的答案。
注意:我对包括考虑bash / Cygwin的最佳实践特别感兴趣。
编辑:到目前为止,似乎没有人提到INT或QUIT,而且HUP的提及也很有限。有没有理由将这些包括在有序的过程中?
答案 0 :(得分:97)
SIGTERM告诉应用程序终止。其他信号告诉应用程序其他与关闭无关但可能有相同结果的事情。不要使用那些。如果您希望关闭应用程序,请告诉它。不要给它误导信号。
有些人认为终止进程的智能标准方法是向其发送大量信号,例如HUP,INT,TERM,最后是KILL。这是荒唐的。终止的正确信号是SIGTERM,如果SIGTERM没有立即终止该过程,那么这是因为应用程序选择处理信号。这意味着它有一个很好的理由不立即终止:它有清理工作要做。如果你用其他信号中断清理工作,就不知道它还没有保存到磁盘中的内存中的哪些数据,哪些客户端应用程序处于挂起状态,或者你是否正在“中等句子”中断它,这实际上是数据损坏。
有关信号真正含义的更多信息,请参阅sigaction(2)。不要将“默认操作”与“描述”混淆,它们不是一回事。
SIGINT用于表示进程的交互式“键盘中断”。有些程序可能会以特殊方式处理这种情况,以便终端用户使用。
SIGHUP用于表示终端已消失且不再查看该过程。就这些。一些进程选择关闭响应,通常是因为没有终端它们的操作没有意义,有些进程选择执行其他操作,例如重新检查配置文件。
SIGKILL用于从内核强制删除进程。它的特殊之处在于它实际上并不是进程的信号,而是由内核直接解释。
不要发送SIGKILL。 SIGKILL肯定不会被脚本发送。如果应用程序处理SIGTERM,它可能需要一秒钟来清理,它可能需要一分钟,可能需要一个小时。取决于应用程序在准备结束之前必须完成的工作。 “假定”应用程序清理序列的任何逻辑已经花了足够长的时间,并且需要在X秒之后是快捷方式或SIGKILLed 只是完全错误。
应用程序需要 SIGKILL终止的唯一原因 - 是在清理序列期间出现问题。在这种情况下,您可以手动打开终端和SIGKILL。除此之外,为什么你要SIGKILL的另一个原因是因为你想要以防止它自我清理。
即使世界上一半的人在5秒后盲目地发送SIGKILL,但仍然是非常错误的事情。
答案 1 :(得分:10)
简短回答:30秒后发送SIGTERM
SIGKILL
。也就是说,发送SIGTERM
,等待一段时间(可能因程序而异,您可能会更好地了解您的系统,但5到30秒就足够了。关闭机器时,您可能会看到它自动等待到1 30s。为什么匆忙,毕竟?),然后发送SIGKILL
。
合理回答:SIGTERM
,SIGINT
,SIGKILL
这绰绰有余。该流程非常可能会在SIGKILL
之前终止。
长答案:SIGTERM
,SIGINT
,SIGQUIT
,SIGABRT
,SIGKILL
这是不必要的,但至少你没有误导有关你的信息的过程。所有这些信号执行意味着您希望进程停止正在执行的操作并退出。
无论您从这个解释中选择什么答案,请记住这一点!
如果您发送的信号意味着其他信号,则该过程可能会以非常不同的方式处理(一方面)。另一方面,如果进程没有处理信号,那么毕竟你发送的内容并不重要,无论如何都会退出进程(当然,当默认操作终止时)。
所以,你必须把自己想象成一个程序员。你会编写一个函数处理程序,比方说,SIGHUP
退出一个与某个东西连接的程序,或者你会循环它以尝试再次连接?这是主要问题!这就是为什么发送意味着你想要的信号很重要的原因。
几乎愚蠢的长答案:
下表包含相关信号,以及程序无法处理时的默认操作。
我按照我建议的顺序订购了它们(顺便说一下,我建议你使用合理的答案,而不是这里的这个),如果你真的需要全部尝试(它会是有趣的是,表格是根据它们可能造成的破坏而排序的,但这不是完全真实的)。
带星号(*)的信号建议 NOT 。关于这些的重要一点是你可能永远不知道它的编程是做什么的。特别是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
。总是用它来测试。
剧本杀人
实际上我对这个问题很感兴趣,于是我决定创建一个小脚本来做到这一点。请随意下载(克隆)它:
GitHub链接到Killgracefully repository
答案 2 :(得分:6)
通常你会发送SIGTERM
,默认为kill。这是默认的原因。只有当程序在合理的时间内没有关闭时才能使用SIGKILL
。但请注意,对于SIGKILL
,程序无法清理数据并且数据可能已损坏。
至于SIGHUP
,HUP
代表“挂断”,历史上意味着调制解调器已断开连接。它基本上等同于SIGTERM
。守护进程有时使用SIGHUP
重新启动或重新加载配置的原因是守护进程从任何控制终端分离,因为守护进程不需要那些,因此永远不会收到SIGHUP
,因此该信号被视为“释放“一般用途。并非所有守护进程都使用它来重新加载! SIGHUP的默认操作是终止,许多守护进程表现如此!所以你不能盲目地将SIGHUP
发送给守护进程并期望它们存活下来。
编辑: SIGINT
可能不适合终止进程,因为它通常与^C
或终端设置中断程序无关。许多程序都是为了自己的目的而捕获它,因此它不常用。 SIGQUIT
通常默认创建核心转储,除非你想要核心文件,否则它也不是一个好的候选者。
摘要:如果您发送SIGTERM
并且该计划未在您的时间范围内死亡,请发送SIGKILL
。
答案 3 :(得分:5)
SIGTERM
实际上意味着向应用程序发送消息:“你会如此善良并自杀”。它可以被应用程序捕获和处理,以运行清理和关闭代码。
SIGKILL
无法被应用程序捕获。应用程序被操作系统杀死而没有任何清理机会。
通常首先发送SIGTERM
,稍稍休息一下,然后发送SIGKILL
。
答案 4 :(得分:3)
答案 5 :(得分:1)
所有讨论都在这里进行,没有提供任何代码。这是我的看法:
#!/bin/bash
$pid = 1234
echo "Killing process $pid..."
kill $pid
waitAttempts=30
for i in $(seq 1 $waitAttempts)
do
echo "Checking if process is alive (attempt #$i / $waitAttempts)..."
sleep 1
if ps -p $pid > /dev/null
then
echo "Process $pid is still running"
else
echo "Process $pid has shut down successfully"
break
fi
done
if ps -p $pid > /dev/null
then
echo "Could not shut down process $pid gracefully - killing it forcibly..."
kill -SIGKILL $pid
fi
答案 6 :(得分:0)
HUP对我来说听起来像垃圾。我发送它来获取守护进程重新读取其配置。
可以拦截SIGTERM;您的守护进程可能会在收到该信号时运行清理代码。你不能为SIGKILL做到这一点。因此,使用SIGKILL,您不会给守护程序的作者任何选项。
的详情