在运行子命令时吞咽用户输入
我正在Ruby中编写一个简单的REPL( adb
的命令行包装器),我支持两种命令:
- 交互式命令
- 非交互式命令
对于2,我只想从REPL调用系统命令,在输出文本时捕获其输出,并允许用户从该命令退回到REPL。 例:
>> logcat ... // log output here ! user hits CTRL-D >> // back at the prompt
这是在我的程序中发生的,而不是系统shell。
现在问题是:当logcat
运行时,父进程(REPL)继续捕获键击,然后在命令退出时立即重放(?)它们。 这意味着,如果例如命中返回几次,然后按CTRL-C,它将退出子命令返回到REPL但重播所有键击,REPL不理解(如果其中一次击键发生要成为CTRL-D,它甚至会无意中退出我的程序……这显然不是我想要的。)
现在我尝试了多种不同的执行子命令的方法(通过反引号,系统,exec),我尝试flush
并rewind
$stdin
然后再回到循环中,我试图捕获CTRL-C中断,但没有任何作用。
我确信Ruby中必须有一种方法:
- 开始一个子过程
- 将所有用户输入路由到该进程并且仅将该进程路由(即不是父进程)
- 在CTRL-C上返回父进程
知道怎么做到这一点?
您可以尝试以下内容:
Signal.trap("INT") {} # ignore sigint in the parent IO.popen "sort" do |io| # run sort in a sub process puts io.read # output stdout end Signal.trap("INT") { exit } # restore sigint while true do puts "looping" sleep 1 end
如果您运行该程序,您可以输入:
$ ruby test.rb c d b ^D b c d looping looping ^C $
要么
$ ruby test.rb c d b ^C looping looping ^C $
它的工作原理是因为popen在子进程中运行命令,该进程有自己的信号处理。