我尝试通过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."
此进程以非零状态退出,表示printenv MY_ENV_VAR
命令失败,并且命令未在同一进程中运行。
如何在单个shell进程中执行一系列命令,记录stdin
,stdout
,stderr
以及每个命令的exitstatus? < / p>
答案 0 :(得分:2)
运行一系列命令的代码很好。问题是您正在错误地设置环境变量。子进程无法像您尝试的那样设置其父进程的环境。子进程确实继承了父进程的环境,因此这是修复代码的一种方法:
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."
使用Ruby 2.3.1在Linux上运行此结果时的结果是:
[["printenv MY_ENV_VAR", "hi\n", "", 0]]
exited with 0 exit status.
现在,如果您想在不修改自己的进程环境的情况下将环境变量传递给子进程,请参阅Open3.capture3
参数的文档:
https://ruby-doc.org/stdlib/libdoc/open3/rdoc/Open3.html#method-c-capture3
答案 1 :(得分:2)
如果您不是必须的话,我强烈建议您不要将多个shell命令链接到一个系统调用中。一个主要的警告是,您无法单独检查链中每个命令的返回码。这导致对命令流的控制不足。例如,如果链中的第一个命令由于任何原因而失败,则无论第一个命令的状态如何,后续命令仍将尝试执行。这可能是不可取的。
我建议将popen功能封装到方法中,然后为要运行的每个命令调用方法。这将允许您在逐个命令的基础上对任何失败的执行做出反应。