Bash 我应该以什么顺序向正常关闭进程发送信号?
在另一篇评论中,评论者说: 除非绝对正确,否则不要使用kill-9 必要的!SIGKILL不会被困在这里的 被终止的程序无法运行任何 关闭例行程序,例如擦除 临时文件。首先尝试HUP(1), 然后是INT(2),然后是QUIT(3) 我原则上同意SIGKILL的说法,但其余的对我来说都是新闻。考虑到Bash 我应该以什么顺序向正常关闭进程发送信号?,bash,signals,job-control,sigterm,Bash,Signals,Job Control,Sigterm,在另一篇评论中,评论者说: 除非绝对正确,否则不要使用kill-9 必要的!SIGKILL不会被困在这里的 被终止的程序无法运行任何 关闭例行程序,例如擦除 临时文件。首先尝试HUP(1), 然后是INT(2),然后是QUIT(3) 我原则上同意SIGKILL的说法,但其余的对我来说都是新闻。考虑到kill发送的默认信号是SIGTERM,我认为这是任意进程正常关闭最常见的预期信号。此外,我还看到了用于非终止原因的SIGHUP,比如告诉守护进程“重新读取配置文件”。在我看来,SIGINT(通常与C
kill
发送的默认信号是SIGTERM
,我认为这是任意进程正常关闭最常见的预期信号。此外,我还看到了用于非终止原因的SIGHUP
,比如告诉守护进程“重新读取配置文件”。在我看来,SIGINT
(通常与Ctrl-C相同的中断,对吧?)没有得到应有的广泛支持,或者终止得相当不快
鉴于SIGKILL
是最后的手段-您应该向任意进程发送哪些信号,以及以什么顺序发送,以便尽可能优雅地关闭它
如果可以的话,请用支持事实(个人偏好或观点除外)或参考资料来证实你的答案
注意:我对包括考虑bash/Cygwin在内的最佳实践特别感兴趣
编辑:到目前为止,似乎没有人提到INT或QUIT,对HUP的提及也有限。是否有任何理由将这些纳入有序杀戮过程?- SIGTERM相当于在窗口中单击“X”
- SIGTERM是Linux在关闭时首先使用的
SIGTERM
,这是kill的默认值。这是一个原因的默认值。只有在程序未在合理的时间内关闭时,才应求助于SIGKILL
。但请注意,使用SIGKILL
时,程序不可能清理任何东西,数据可能会损坏
至于SIGHUP
,HUP
代表“挂断”,在历史上意味着调制解调器断开连接。它本质上相当于SIGTERM
。守护进程有时使用SIGHUP
重新启动或重新加载配置的原因是,守护进程从任何控制终端分离,因为守护进程不需要这些终端,因此永远不会接收SIGHUP
,因此该信号被视为“释放”供一般使用。并非所有守护进程都使用此选项进行重新加载!SIGHUP的默认操作是终止,许多守护进程都是这样运行的!因此,您不能盲目地向守护进程发送SIGHUP
s并期望它们生存下来
编辑:SIGINT
可能不适合终止进程,因为它通常绑定到^C
或任何终端设置来中断程序。许多程序捕捉到这一点是出于自己的目的,因此这一点很常见,以至于它无法正常工作SIGQUIT
通常具有创建核心转储的默认设置,除非您希望核心文件被放置在周围,否则它也不是一个好的候选者
小结:如果你发送了
SIGTERM
,并且程序没有在你的时间范围内死掉,那么发送它SIGKILL
HUP对我来说听起来像垃圾。我会将其发送给守护进程以重新读取其配置
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可以被截获;您的守护进程可能只有在接收到该信号时才能运行清理代码。你不能为了西格尔那样做。因此,对于SIGKILL,您不会给守护程序的作者任何选项
关于SIGTERM的更多信息实际上意味着向应用程序发送一条消息:“你会这么好心,自杀吗?”。它可以被应用程序捕获和处理,以运行清理和关闭代码
SIGKILL
无法被应用程序捕获。应用程序被操作系统杀死,没有任何清理的机会
典型的做法是先发送
SIGTERM
,休眠一段时间,然后发送SIGKILL
SIGTERM告诉应用程序终止。其他信号告诉应用程序其他与关机无关的事情,但有时可能会产生相同的结果。不要用那些。如果您想让应用程序关闭,请告诉它。不要给它错误的信号
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
有些人认为,终止进程的智能标准方法是向进程发送一系列信号,如HUP、INT、TERM和finally KILL。这太荒谬了。正确的终止信号是SIGTERM,如果SIGTERM没有立即终止进程,这可能是因为应用程序选择了处理该信号。这意味着它有一个很好的理由不立即终止:它有清理工作要做。如果您使用其他信号中断清理工作,则无法知道内存中哪些数据尚未保存到磁盘,哪些客户端应用程序处于挂起状态,或者您是否正在中断“中间语句”,这实际上是数据损坏
有关信号真正含义的更多信息,请参阅sigaction(2)。不要混淆“默认操作”和“描述”,它们不是一回事
SIGINT用于向进程的交互式“键盘中断”发送信号。为了终端用户的目的,一些程序可能会以特殊的方式处理这种情况
SIGHUP用于表示终端已消失,不再查看进程。仅此而已。有些进程选择关闭作为响应,通常是因为没有终端它们的操作毫无意义,有些进程选择执行其他操作,例如重新检查配置文件
SIGKILL用于强制从内核中删除进程。它的特殊之处在于它实际上不是进程的信号,而是由内核直接解释的
不要发送SIGKILL。SIGKILL肯定不会发送
#!/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