holdtom
正确和安全地这样做的简单方法是使用Open3.capture2(), Open3.capture2e(),或Open3.capture3().用红宝石的后背和它的%x别名是在任何情况下都不安全如果与不受信任的数据一起使用。它是危险简单明了:untrusted = "; date; echo"out = `echo #{untrusted}`
# BADuntrusted = '"; date; echo"'out = `echo "#{untrusted}"`
# BADuntrusted = "'; date; echo'"out = `echo '#{untrusted}'`
# BAD这个system相反,函数正确地转义参数。如果使用正确:ret = system "echo #{untrusted}"
# BADret = system 'echo', untrusted
# good问题是,它返回退出代码而不是输出,而捕获输出则是复杂和混乱的。到目前为止,这个线程中最好的答案提到了Open3,但没有提到最适合该任务的函数。Open3.capture2, capture2e和capture3干得像system,但返回两个或三个参数:out, err, st = Open3.capture3("echo #{untrusted}")
# BADout, err, st = Open3.capture3('echo', untrusted)
# goodout_err, st = Open3.capture2e('echo', untrusted)
# goodout, st = Open3.capture2('echo', untrusted)
# goodp st.exitstatus另一位提到IO.popen()..语法可能很笨拙,因为它需要一个数组作为输入,但它也能工作:out = IO.popen(['echo', untrusted]).read
# good为了方便起见,你可以把Open3.capture3()在一项职能中,例如:## Returns stdout on success, false on failure, nil on error#def syscall(*cmd)
begin
stdout, stderr, status = Open3.capture3(*cmd)
status.success? && stdout.slice!(0..-(1 + $/.size)) # strip trailing eol
rescue
endend例子:p system('foo')p syscall('foo')p system('which', 'foo')p syscall('which', 'foo')p system('which', 'which')p syscall('which', 'which')产生以下结果:nilnilfalsefalse/usr/bin/which <— stdout from system('which', 'which')true
<- p system('which', 'which')"/usr/bin/which" <- p syscall('which', 'which')