我需要的是:
在调用系统命令之前执行某些操作。
执行我的系统命令
涉及提示和获取用户的答案
保持ctrl-c对被叫命令的影响不变
获取我的系统命令的结果并继续执行更多ruby代码
到目前为止,我尝试了类似的内容:
#!/usr/bin/env ruby
p "Foo"
exit_value = exec 'heroku run console'
p "Bar"
exit exit_value
这个失败是因为exec替换并终止了当前进程,因此在exec之后不再执行ruby代码
我已经阅读过这篇文章了: How to run code after ruby Kernel.exec
我尝试使用内核#system调用:
#!/usr/bin/env ruby
p "Foo"
system 'heroku run console'
p "Bar"
exit $?
这个也失败了,因为ctrl-c显然被我的ruby进程捕获并杀死它而不是达到它预期的目标。
那么,有没有办法处理这些特殊要求?
答案 0 :(得分:1)
非常感谢hek2mgl指向正确的方向:
include Signal
include Process
# Handling SIGINT by doing nothing prevents default behaviour
# (killing both processes)
Signal.trap("INT") {}
# Fork off subprocess (so exec won't exit from your main process)
pid = fork
if pid == nil then
# Child code. Use exec(!) to avoid the signal handler
# getting called in the child.
exec 'heroku run console'
else
# Wait for subprocess to exit
wait pid
# "wait" sets the $? according to the subprocess exit status
exit_status = $?.exitstatus
p "Execute more ruby code"
exit exit_status
end
答案 1 :(得分:0)
我会为SIGINT
安装一个信号陷阱,分离子进程,执行命令(以防止信号处理程序在父进程和子进程中运行)并在发生SIGINT
时终止子进程:
include Signal
include Process
# Define a signal handler for SIGINT
Signal.trap("INT") do
if $pid != nil then
# Kill the subprocess
Process.kill("INT", $pid)
else
# Terminate ourself
exit 1
end
end
# Fork off subprocess
# The $ marks the variable as global
$pid = fork
if $pid == nil then
# Child code. Use exec(!) to avoid the signal handler
# getting called in the child.
exec 'bash -c "echo test; sleep 3; echo test"'
end
# Wait for subprocess to exit
wait $pid
# Reset $pid
$pid = nil
exit_status = $?.exitstatus
# Detect whether the child process has been killed
if exit_status == nil then
p "Child process has been killed."
end
p "Execute more ruby code"
...