发布于2026-06-29 阅读(0)
扫一扫,手机访问
Process.kill(signal, pid, ...) → integer
先来看Process.kill的作用:发送指定的信号给一个或多个进程或进程组。它的行为取决于pid参数的取值——这几个规则其实很直白:

pid>0,那就发送信号给指定PID的那个进程。pid=0,信号会发给调用kill的进程所在进程组里的所有进程。pid<0,情况稍微复杂一点,得看操作系统。以Linux为例:pid=-1时,信号会发给除了init进程(PID=1)以外的所有进程——当然,没有权限的进程会被跳过。pid<-1时,信号发给-pid这个进程所在的进程组里的所有进程。比如-3000,就是把信号发给PID为3000的进程所在的整个进程组。那么Process.kill的第一个参数——信号——怎么指定?
INT、SIGINT、1都是有效的。-2或-INT),意思是发送给进程所在的进程组,而不是具体的进程。不过Linux不支持这种写法。pid = fork do
sleep 300
end
# ...
Process.kill("HUP", pid)
Process.wait
在Ruby里,捕获信号并定义处理逻辑,用的是Kernel.trap或Signal.trap,这俩完全等价。可以同时为多个信号设置不同的trap。
Signal.trap(0, proc { puts "Terminating: #{$$}" })
Signal.trap("CLD") { puts "Child died" }
fork && Process.wait
=begin
Terminating: 27461
Child died
Terminating: 27460
=end
trap的第一个参数是要监控的信号,同样可以是字符串名(比如SIGINT)、省略SIG前缀的名字(比如INT),或者数值(比如2)。Ruby还支持一个特殊的信号0,对应的字符串名字是EXIT或SIGEXIT——它会在进程退出时触发。
第二个参数或者代码块,就是捕获信号后要执行的内容。第二个参数有几种特殊的字符串值:
IGNORE或SIG_IGN:忽略这个信号。DEFAULT或SIG_DFL:按Ruby的默认处理规则来。EXIT:以状态码0退出当前进程。SYSTEM_DEFAULT:按系统的默认信号处理规则,一般是以状态码141退出。用第三方库的时候,经常不确定它有没有给某个信号注册处理程序——就算知道它注册了,自己也想追加逻辑,但不想覆盖人家的处理。怎么办?巧用trap的返回值就行。每次调用trap,它都会返回之前已经注册的处理程序(一个Proc对象)。不过要注意:有些信号的初始处理程序是字符串DEFAULT,而不是Proc对象,所以得做类型判断:
# 第一次定义INT的信号处理程序
first_trap = trap('INT') {
first_trap.call if first_trap.is_a? Proc
puts "first_trap"
}
# 第二次定义INT的信号处理程序
old_trap = trap('INT') {
old_trap.call if old_trap.is_a? Proc # 调用第一次定义的信号处理程序
puts "old trap" # 本次trap时执行的逻辑
}
# 定义好之后,old_trap为第一次定义的信号处理程序
# 之后按下CTRL+C触发INT信号的信号处理程序
如果是在多线程环境里注册信号处理程序,有一个重要规则:信号处理程序总是注册在所在进程的main线程中——哪怕你是在其他线程里调用的trap()。来看个例子:
pid = fork do
puts "main Thread: #{Thread.current}"
Thread.new {
puts "new Thread: #{Thread.current}"
trap("TERM", proc { puts "Signal: #{Thread.current}" })
sleep 2
}
sleep 2
end
sleep 1
Process.kill 'SIGTERM', pid
=begin
main Thread: #
new Thread: #
Signal: #
=end
输出很说明问题:信号处理实际是在main线程里执行的,而不是在那个新线程里。
子进程会从父进程那里继承信号处理程序。这一点可能出乎意料,但确实如此:
trap 'TERM', proc { puts "Signal: #{Process.pid}" }
puts "Parent: #{Process.pid}"
pid = fork do
sleep 30
end
puts "Child: #{pid}"
Process.kill 'TERM', pid
=begin
Parent: 2872
Child: 2901
Signal: 2901
=end
可以看到,子进程的TERM信号处理程序直接继承自父进程——这在设计多进程架构时是个需要留意的细节。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8