用 Linux 的同学们帮忙打开 irb 或者 pry 试下下面两行代码:
2.0.0p247 > system "xclip .bashrc" => true 2.0.0p247 > `xclip .bashrc` # irb hangs!
完全想不通 irb 为什么会挂起啊,查了下文档, Kernel#` 和 Kernel#system 都是在 subshell 里跑命令,只是前者返回标准输出结果,后者返回 true, false 或 nil
Kernel#`
Kernel#system
true
false
nil
上面是让 xclip 的标准输出到 irb 了 下面是建立了管道,要等到 xclip 输出 EOF 才能返回
#1 楼 @luikore
不对啊, xclip 为什么会建立管道,只是读取.bashrc的内容到primary selection, 况且这时候摁 Ctrl-d 也没用
xclip
.bashrc
primary selection
哦,早上起来换到 root 再试了一下,这次xclip .bashrc 正常返回了,但是:
root
xclip .bashrc
irb(main):002:0> require 'benchmark' => true irb(main):003:0> puts Benchmark.measure { system "xclip .bashrc" } 0.000000 0.000000 0.000000 ( 0.007043) => nil irb(main):004:0> puts Benchmark.measure { `xclip .bashrc` } 0.000000 0.000000 0.010000 ( 19.856729) => nil
可以看看 Benchmark.measure 的源码,可能使用了 Thread.new
#3 楼 @sevk 应该和 Benchmark.measure 无关,因为 `xclip .bashrc` 慢了快 20 秒,不用 Benchmark 也能明显的感觉到
Benchmark.measure
`xclip .bashrc`
Benchmark
果然啊,我这里要 24 秒
[8] pry(main)> puts Benchmark.measure { `xclip .vimrc` } 0.000000 0.000000 0.000000 ( 24.320067) => nil
#2 楼 @toctan
`` 就是接受进程的 stdout 输出,并变成字符串。需要等 EOF.
system 在起的那个进程退出时就自然退出了。
system
而等待 stdout 退出,需要等到它的所有子进程都退出。
把下面代码存为 xclip2, 自己看看 system "./xclip2" 和 `./xclip2` 的区别吧
xclip2
system "./xclip2"
`./xclip2`
#! /usr/bin/env ruby fork do sleep 3 print '' end
你的调用明显是不需要其输出结果的,用 `` 就白白等待 EOF 了。
#6 楼 @luikore 我懂你的意思了,再加上 Stackoverflow 上的另一条回答就能够解释为什么`xclip .bashrc` 多花这么多时间了:
$ xclip -verbose .bashrc Connected to X server. Using UTF8_STRING. Reading .bashrc... Waiting for selection requests, Control-C to quit
问题在于 xclip 不会自己 terminate,要等待 selection requests, `xclip .bashrc` 之后如果马上用鼠标选点什么东西,他就会马上返回结果。
terminate
selection requests
http://stackoverflow.com/questions/19237559/why-xclip-bashrc-takes-much-longer-than-systemxclip-bashrc-in-ruby