由报错:syscall.SIGKILL cannot be trapped引出的kill -9 与 kill -15的区别

最近搞一个agent,需要完成一个类似于
./agent start
./agent stop

当agent start之后,希望通过./agent stop终止agent的运行。
这本质上是一个进程间通信问题,这里我用到了信号signal:syscall.SIGKILL 以及 syscall.SIGTERM
用于监听信号的主进程代码如下:

signal.Notify(c, syscall.SIGKILL, syscall.SIGTERM)

此时用gofmt运行了一把发现报了这个玩意儿出来:
syscall.SIGKILL cannot be trapped

这个是什么意思捏?这里不得不说到kill -9 与 kill -15的区别了,
-9就是发送syscall.SIGKILL 信号,-15就是发送syscall.SIGTERM信号,这个可以在代码里点开看下:
在这里插入图片描述
16进制表示0x9 就是9,0xf 就是15

这两个到底区别在哪里呢?

-9 指定 kill 强制终止进程,这在某种情况下可能会造成问题,常常是进程所占有的某些资源没有正常释放的问题。
可以使用 kill 的默认发送信号 SIGTERM 来让进程正常终止。

《APUE》 中对 SIGTERM 信号的讲解内容如下:
这是 kill 命令在默认情况下发送的终止信号。因为它可以被应用程序捕捉到,因此使用 SIGTERM 能够给应用程序一个在 exit 之前执行回收工作优雅终止的机会(与 SIGKILL 正相反, SIGKILL 不能被捕捉到或忽略)。

早在几年前我其实说听说过-15比-9要优雅,到底优雅在什么地方,为什么SIGTERM可以在exit之前执行回收工作?为什么SIGKILL不行呢?
直接上代码~

主进程的代码:

func StartDaemon() {
	c := make(chan os.Signal, 1)
	// SIGKILL will force kill the Progress,Unable to handle and ignore the signal.
	// SIGTERM elegant, allowing to catch signals and do processing after exit
	signal.Notify(c, syscall.SIGKILL, syscall.SIGTERM)
	<-c
	fmt.Printf("这里执行了")
	// there maybe send the status to the server in the future
	os.Exit(0)
}

发送kill信号的代码:

// 这里的process就是上面的主进程结构体
err := process.Signal(syscall.SIGKILL)

当发送SIGKILL信号到主进程时,实际上
fmt.Printf(“这里执行了”) 这句话是不会执行的。因为KILL信号会直接立即终止该进程。

然而如果
发送kill信号的代码改为:

// 这里的process就是上面的主进程结构体
err := process.Signal(syscall.SIGTERM)

fmt.Printf(“这里执行了”) 这条是会执行的。这里就真的明白了所谓的优雅退出的问题。

我理解 除SIGKILL以外,其他信号包括SIGTERM,只是一个规范,这个信号是可以捕获后,写代码的人可以根据接收到的信号进行后续处理。所以所谓的“优雅”退出,其实是如果程序员写的代码,在有需要的条件下(例如停止主进程前,需要进行一些文件清理、连接关闭相关的事情) 在接收到信号之后,可以处理上述的一些逻辑,然后自己再主动调用os.exit(0)退出,而kill信号是直接退出不会理会程序员的后续逻辑了。

所以人云亦云:kill -15 pid更加优雅,kill -9 pid强制退出不够优雅,这句话现在应该理解为,如果程序员的代码里实现了-15的信号处理逻辑,在stop任务前去完成一些相关后续任务,这就是优雅的。如果程序员没有实现这个逻辑 -15有何用?所以是否优雅退出 重心应该是在程序员实现一个程序的逻辑里,而不是-15 或者-9 谁更优雅。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值