推薦在 Ruby 中執行 shell 程式碼的方法

Open3.popen3 或 Open3.capture3:
Open3 實際上只使用 Ruby 的 spawn 命令,但為你提供了更好的 API。

Open3.popen3

Popen3 在子程序中執行並返回 stdin,stdout,stderr 和 wait_thr。

require 'open3'
stdin, stdout, stderr, wait_thr = Open3.popen3("sleep 5s && ls")
puts "#{stdout.read} #{stderr.read} #{wait_thr.value.exitstatus}"

要麼

require 'open3'
cmd = 'git push heroku master'
Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
  puts "stdout is:" + stdout.read
  puts "stderr is:" + stderr.read
end

將輸出: stdout is:stderr is:fatal:不是 git 儲存庫(或任何父目錄):。git

要麼

require 'open3'
cmd = 'ping www.google.com'
Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
  while line = stdout.gets
    puts line
  end
end

將輸出:

使用 32 個位元組的資料 ping www.google.com [216.58.223.36]:

216.58.223.36 的回覆:bytes = 32 time = 16ms TTL = 54
來自 216.58.223.36 的回覆:bytes = 32 time = 10ms TTL = 54
來自 216.58 的回覆 .223.36:bytes = 32 time = 21ms TTL = 54
來自 216.58.223.36 的回覆:bytes = 32 time = 29ms TTL = 54
Ping 統計資料為 216.58.223.36:
資料包:已傳送= 4,已接收= 4,已丟失= 0(0%損失),
以毫秒為單位的近似往返時間:
最小值= 10ms,最大值= 29ms,平均值= 19ms

Open3.capture3:

require 'open3'

stdout, stderr, status = Open3.capture3('my_funky_command', 'and', 'some', 'argumants')
if status.success?
  # command completed successfully, do some more stuff
else
  raise "An error occured"
end

要麼

Open3.capture3('/some/binary with some args')  

不推薦,但由於額外的開銷和殼注入的可能性。

如果命令從 stdin 讀取並且你想要為它提供一些資料:

Open3.capture3('my_funky_command', stdin_data: 'read from stdin')  

使用 chdir 執行具有不同工作目錄的命令:

Open3.capture3('my_funky_command', chdir: '/some/directory')