Ruby 在同一shell进程中运行多个命令

Ruby 在同一shell进程中运行多个命令,ruby,shell,Ruby,Shell,我试图通过Ruby运行一系列命令,并捕获stdin、stdout、stderr和exitstatus require "open3" require "pp" command_list = [ "export MY_ENV_VAR=foobar", "printenv MY_ENV_VAR" ] executed_commands = [] result = nil command_list.each do |command| stdout, stderr, status =

我试图通过Ruby运行一系列命令,并捕获
stdin
stdout
stderr
和exitstatus

require "open3"
require "pp"

command_list = [
  "export MY_ENV_VAR=foobar",
  "printenv MY_ENV_VAR"
]

executed_commands = []
result = nil

command_list.each do |command|
  stdout, stderr, status = Open3.capture3(command)
  result = status.exitstatus
  executed_commands << [command, stdout, stderr, result]
  break if result != 0
end

pp executed_commands
puts "exited with #{result} exit status."
需要“open3”
需要“pp”
命令列表=[
“导出MY_ENV_VAR=foobar”,
“打印环境我的环境变量”
]
已执行的_命令=[]
结果=零
命令列表。每个do命令|
stdout,stderr,status=Open3.capture3(命令)
结果=status.exitstatus

执行的命令运行一系列命令的代码很好。问题是您未正确设置环境变量。子进程无法像您尝试的那样设置其父进程的环境。子进程确实继承了其父进程的环境,因此这里有一种修复代码的方法:

require "open3"
require "pp"

ENV['MY_ENV_VAR'] = 'hi'

command_list = [
  "printenv MY_ENV_VAR"
]

executed_commands = []
result = nil

command_list.each do |command|
  stdout, stderr, status = Open3.capture3(command)
  result = status.exitstatus
  executed_commands << [command, stdout, stderr, result]
  break if result != 0
end

pp executed_commands
puts "exited with #{result} exit status."
现在,如果希望在不修改自己进程的环境的情况下将环境变量传递给子进程,请参阅文档以获取
Open3.capture3
的参数:


我强烈建议您不要将多个shell命令链接到一个系统调用中,如果您不一定要这样做的话。一个主要的警告是,您不能单独检查链中每个命令的返回代码。这导致对命令流缺乏控制。例如,如果链中的第一个命令因任何原因失败,则无论第一个命令的状态如何,后续命令仍将尝试执行。这可能是不可取的


我建议将popen功能封装到一个方法中,只需为每个要运行的命令调用该方法。这将允许您逐个命令地对任何失败的执行做出反应。

我如何创建父shell进程,然后在该shell中执行一系列命令?您可以尝试将多个命令分隔为一个字符串,并使用
&&
将它们分隔开。我建议使用前者,因为它会在出现错误时停止。在一次调用中运行多个命令时,虽然您不能单独检查返回代码,但通过将命令与
&&
而不是
连接,可以避免在失败时继续出现问题。这是真的。根据经验,我会更轻松地处理这件事。同样,如果您没有严格的技术理由来组合命令,请避免使用它。此外,这种方法还存在安全隐患,但这超出了这个问题的范围。
[["printenv MY_ENV_VAR", "hi\n", "", 0]]
exited with 0 exit status.