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

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-9 必要的!SIGKILL不会被困在这里的 被终止的程序无法运行任何 关闭例行程序,例如擦除 临时文件。首先尝试HUP(1), 然后是INT(2),然后是QUIT(3)

我原则上同意SIGKILL的说法,但其余的对我来说都是新闻。考虑到
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