我正在使用 Debian Stretch (systemd)。我在前台运行 rsyslog 守护进程,
/usr/sbin/rsyslogd -n
并使用Ctrl+Z来停止它。进程的状态更改为Tl
(已停止,已线程化)。我向该进程发出了多个命令,并且该进程的状态是相同的:。一旦我做了,它就死了。我有 3 个问题。kill -15 <pid>
Tl
fg
- 为什么
SIGSTOP
-ed 进程没有响应SIGTERM
?为什么内核保持它处于相同的状态? - 为什么它一收到
SIGCONT
信号就被杀了? - 如果是因为之前的
SIGTERM
信号,那么在进程恢复之前它会保存在哪里?
答案1
SIGSTOP
和SIGKILL
是进程无法捕获和处理的两个信号。SIGTSTP
就像SIGSTOP
除了它能被抓住并处理。
SIGSTOP
和信号SIGTSTP
停止进程,为 做好准备SIGCONT
。当您向该进程发送 a 时SIGTERM
,该进程未运行,因此无法运行代码来退出。
(还有 和SIGTTIN
,SIGTTOU
它们是当后台作业尝试读取或写入终端时由 TTY 层生成的信号。它们可以被捕获,但否则会停止(挂起)进程,就像 一样SIGTSTP
。但我现在要在这个答案的其余部分忽略这两个。)
您CtrlZ发送进程 a SIGTSTP
,该进程似乎没有以任何方式进行特殊处理rsyslogd
,因此它只是挂起进程挂起SIGCONT
或SIGKILL
。
这里的解决方案也是SIGCONT
在你之后发送SIGTERM
,以便进程可以接收和处理信号。
例子:
sleep 999 &
# Assume we got PID 456 for this process
kill -TSTP 456 # Suspend the process (nicely)
kill -TERM 456 # Terminate the process (nicely). Nothing happens
kill -CONT 456 # Continue the process so it can exit cleanly
的文档GNU C 库我认为(我的重点)很好地解释了这一点:
当进程停止时,在进程继续运行之前,无法再向其传递任何信号,除了
SIGKILL
信号和(显然)SIGCONT
信号。信号被标记为待处理,但在进程继续之前不会传递。该SIGKILL
信号总是导致进程终止,并且不能被阻止、处理或忽略。您可以忽略SIGCONT
,但如果进程停止,它总是会导致进程继续运行。SIGCONT
向进程发送信号会导致该进程的任何挂起的停止信号被丢弃。同样,SIGCONT
当进程收到停止信号时,该进程的任何待处理信号都会被丢弃