Ruby信号处理详解
Ruby使用Process.kill发送信号
Process.kill(signal, pid, ...) → integer
Process.kill发送指定的信号给一个或多个进程或进程组:
pid>0,表示发送信号给指定PID的进程如果目标pid=0,表示发送信号给调用kill的进程所在进程组的所有进程如果目标pid<0,表示按照操作系统的规则发送信号。对于Linux来说:如果pid=-1,表示发送信号给除pid=1的init进程外的所有进程,当然,没有权限的进程将不受影响如果pid<-1,表示发送信号给-pid所在进程组的所有进程,例如-3000表示发送信号给pid=3000的进程所在进程组的所有进程
Process.kill的第一个参数是要发送的信号:
-2或-INT),表示发送信号给进程所在进程组而非指定的进程(Linux不支持带负号的信号)如果信号为0,表示探测是否能发送信号给目标进程,可探测是否能管理目标进程或者探测目标进程是否存活
pid = fork do
sleep 300
end
# ...
Process.kill("HUP", pid)
Process.waitRuby使用trap()设置信号处理程序
Ruby中使用Kernel.trap或Signal.trap捕获信号并设置信号处理程序,这两个trap等价。
可设置多个trap来监控多个信号。
Signal.trap(0, proc { puts "Terminating: #{$$}" })
Signal.trap("CLD") { puts "Child died" }
fork && Process.wait
=begin
Terminating: 27461
Child died
Terminating: 27460
=endtrap的第一个参数是监控的信号名称,可以是字符串的信号名称(如SIGINT),可以是省略SIG前缀的信号名称(如INT),可以是信号对应的数值(如2)。
Ruby支持一个特殊的信号0(对应的字符串信号名为EXIT或SIGEXIT),表示进程退出时会触发的信号。
trap的第二个参数或语句块是捕获到信号后执行的代码。第二个参数有几种特殊情况:
如果第二个参数为字符串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 子进程继承信号处理程序
子进程会从父进程继承信号处理程序。
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更多关于Ruby信号处理的知识请查看下面的相关链接
X 关闭
X 关闭
- 15G资费不大降!三大运营商谁提供的5G网速最快?中国信通院给出答案
- 2联想拯救者Y70发布最新预告:售价2970元起 迄今最便宜的骁龙8+旗舰
- 3亚马逊开始大规模推广掌纹支付技术 顾客可使用“挥手付”结账
- 4现代和起亚上半年出口20万辆新能源汽车同比增长30.6%
- 5如何让居民5分钟使用到各种设施?沙特“线性城市”来了
- 6AMD实现连续8个季度的增长 季度营收首次突破60亿美元利润更是翻倍
- 7转转集团发布2022年二季度手机行情报告:二手市场“飘香”
- 8充电宝100Wh等于多少毫安?铁路旅客禁止、限制携带和托运物品目录
- 9好消息!京东与腾讯续签三年战略合作协议 加强技术创新与供应链服务
- 10名创优品拟通过香港IPO全球发售4100万股 全球发售所得款项有什么用处?

