运行 ruby 当前终端中的命令然后在退出时执行代码
Run a command in current terminal in ruby then execute code when it exits
我需要的是:
在调用系统命令之前执行某些操作。
执行我的系统命令
涉及提示并从用户那里获得答案
保持 ctrl-c 对被调用命令的影响不变
获取我的系统命令的结果并继续执行更多ruby代码
到目前为止,我尝试了类似的东西:
#!/usr/bin/env ruby
p "Foo"
exit_value = exec 'heroku run console'
p "Bar"
exit exit_value
这个失败是因为 exec 替换并终止了当前进程,所以在 exec
之后不再执行 ruby 代码
我已经读过这个post:
How to run code after ruby Kernel.exec
我尝试使用 Kernel#system 调用:
#!/usr/bin/env ruby
p "Foo"
system 'heroku run console'
p "Bar"
exit $?
这个也失败了,因为 ctrl-c 显然被我的 ruby 进程捕获并杀死了它而不是到达预期目标。
那么,有没有办法处理这些奇特的需求呢?
我会为 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"
...
非常感谢 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
我需要的是:
在调用系统命令之前执行某些操作。
执行我的系统命令
涉及提示并从用户那里获得答案
保持 ctrl-c 对被调用命令的影响不变
获取我的系统命令的结果并继续执行更多ruby代码
到目前为止,我尝试了类似的东西:
#!/usr/bin/env ruby
p "Foo"
exit_value = exec 'heroku run console'
p "Bar"
exit exit_value
这个失败是因为 exec 替换并终止了当前进程,所以在 exec
之后不再执行 ruby 代码我已经读过这个post: How to run code after ruby Kernel.exec
我尝试使用 Kernel#system 调用:
#!/usr/bin/env ruby
p "Foo"
system 'heroku run console'
p "Bar"
exit $?
这个也失败了,因为 ctrl-c 显然被我的 ruby 进程捕获并杀死了它而不是到达预期目标。
那么,有没有办法处理这些奇特的需求呢?
我会为 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"
...
非常感谢 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