编写一个cli工具,在启动时打开OS X Web代理,在关机时我想再次将其关闭。捕获SIGINT并执行应用清理的正确方法是什么?尝试以下操作,它跟踪消息,但不运行系统命令或退出:
Signal::INT.trap do
puts "trap"
fork do
system "networksetup -setwebproxystate Wi-Fi off"
end
exit
end
此代码确实退出,但给出了“无效的内存访问”错误
at_exit do
fork do
system "networksetup -setwebproxystate Wi-Fi off"
end
end
LibC.signal Signal::INT.value, ->(s : Int32) { exit }
Invalid memory access (signal 10) at address 0x10d3a8e00
[0x10d029b4b] *CallStack::print_backtrace:Int32 +107
[0x10d0100d5] __crystal_sigfault_handler +181
[0x7fff6c5b3b3d] _sigtramp +29
更新
这是使用Signal::INT.trap
的完整“应用程序”,对我来说,这将正确打开和关闭OS X代理设置,但在中断信号发出后,循环将继续运行。
fork do
system "networksetup -setwebproxy Wi-Fi 127.0.0.1 4242"
end
Signal::INT.trap do
puts "trap"
fork do
system "networksetup -setwebproxystate Wi-Fi off"
end
exit
end
loop do
sleep 1
puts "foo"
end
答案 0 :(得分:4)
您可以使用Fibers吗?
docker run --rm --volumes-from my-mongo-container -v $(pwd):/out ubuntu tar cvf /out/mongo-data-db.tar
答案 1 :(得分:2)
恕我直言,麻烦来自Crystal-lang的fork
,它具有一些奇怪的语义。
当您尝试启动工作流程来运行system
调用时,Crystal也复制了loop
...
执行exit
时,第一个循环退出,而不是分叉的循环。
要验证这一点,您可以像这样在sleep
和fork
块中写入一些INT.trap
:
fork do
system "echo \"start\""
end
Signal::INT.trap do
puts "trap"
fork do
system "echo \"off\""
sleep 15
end
sleep 20
exit
end
loop do
sleep 1
puts "foo"
end
然后尝试连续观察ps
命令的结果。
@Sergey Fedorov已使用纤维回答了替代方法。