在同一个shell进程中运行多个命令
我试图通过Ruby运行一系列命令,并捕获stdin
,stdout
,和exitstatus。在同一个shell进程中运行多个命令
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
失败,并且这些命令不被在同一进程中运行。
如何可以在一个单一的外壳进程执行的一系列命令,记录stdin
,stdout
,stderr
和每个命令的退出状态?
用于运行一系列命令的代码很好。问题在于你错误地设置了环境变量。子进程不能像你想要做的那样设置父进程的环境。子进程做继承其父的环境,所以这里是修复你的代码的一种方法:
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
我强烈建议您不要将多个shell命令链接到一个系统调用中,如果您没有必要的话。一个重要的警告是你不能单独检查链中每个命令的返回代码。这导致对命令流程缺乏控制。例如,如果链中的第一个命令因任何原因失败,则后续命令仍会尝试执行,而不管第一个命令的状态如何。这可能是不可取的。
我建议将popen功能封装到一个方法中,并且只是为每个要运行的命令调用方法。这将允许您对每个命令执行失败做出反应。
在一次调用中运行多个命令时,虽然不能单独检查返回代码,但可以通过用'&&而不是';'加入命令来避免继续失败的问题。 –
这是真的。作为一个经验法则,我会更加轻松地处理这个问题。同样,如果你没有严格的技术理由来组合命令,请避免它。此外,这种方法还有安全隐患,但这不在这个问题的范围之内。 – Jakir00
我将如何创建一个父shell进程,然后在该shell中执行一系列命令? – Richard
你可以试着把多个命令放在一个字符串中,并用'&&'或';'分隔它们。我建议前者,因为只要出现错误就会停止。 –