![](/img/trans.png)
[英]How do I source environment variables for a command shell in a Ruby script?
[英]How can I import environment variables from a shell script into the current Ruby environment?
我有一系列bash文件,我想将它们提供给当前的Ruby环境。 这是一个例子:
$ echo "export FOO=bar" > foo.sh
$ irb
> `source $(pwd)/foo.sh`
> puts ENV['FOO']
=> nil
有没有一种方法可以将foo.sh
来源到父环境中而无需手动解析它?
Ruby中的所有shell调用都在子Process
中运行,无论您使用system()
还是反引号,还是使用Process
或任何其他机制来执行它们。 像这样的子流程不可能影响当前的Ruby流程。
如果要在执行某些Ruby代码之前先获取Shell脚本,则可以创建包装器:
#!/bin/sh
source foo.sh
ruby some_ruby_file.rb
如果确实需要,您可以尝试从shell脚本中解析出变量导出,然后直接设置Ruby的ENV
哈希,但这几乎肯定是个坏主意。 很难编写,容易出错且难以维护。
可以使用上述包装器,也可以使用其他方法保存环境配置,例如YAML文件或其他常规配置解决方案。
您不能从子进程或子Shell更改父进程的环境,但是可以肯定地将文件来源或解析为当前进程。
您可以使用Kernel#load或Kernel#require方法来获取Ruby脚本。 这会将文件的内容导入到您当前的进程中。
如果您的源文件是shell脚本,则不能简单地将其作为Ruby加载; 您将需要执行某种类型的文件解析。 除非您信任所读取文件的内容,格式和源,否则这可能会带来安全风险。
假设您信任您的输入源,并给出了一个示例文件,例如:
#!/usr/bin/bash
export FOO='bar'
echo FOO
echo bar
echo "FOO=$FOO"
您可以执行以下操作:
# Find variables in the general form of "export x=y"
env_vars = File.read('/tmp/file.txt').scan /export\s+(\S+)=(\S+)/
#=> [["FOO", "'bar'"]]
# Parse each variable into the Ruby ENV key/value pair, removing
# outer quotes on the value if present.
env_vars.each { |v| ENV[v.first] = v.last.gsub /\A['"]|['"]\Z/, '' }
# Verify you have the value you expect.
ENV['FOO']
#=> "bar"
这会将通过String#scan方法找到的每个变量添加到ENV中 ,然后可以通过其键对其进行访问。
通常,如果您尝试从脚本内部设置配置选项,则最好加载YAML文件或使用OptionParser 。 特别是YAML文件易于阅读,易于解析,可人工编辑以及(相对)易于清理。 你的旅费可能会改变。
我几乎得到了一些答案,但没有一个完全适合我的情况,这就是我最终要做的事情:
file = Pathname.new "tmp-variables.txt"
`env -i /bin/sh -c 'source <myfile-here.sh> && env > #{file}'`
file.each_line do |line|
line.match(/(?<key>[^=]+)=(?<value>.+)/) {|match| ENV[match[:key]] = match[:value] }
end
这是一个示例脚本,显示了它的运行情况:
require 'pathname'
file = Pathname.new "tmp-variables.txt"
`mkdir profile.d`
`echo "export FOO=${FOO:-'bar'}" > profile.d/node`
`touch #{file}`
`env -i /bin/sh -c 'source profile.d/node && env > #{file}'`
file.each_line do |line|
line.match(/(?<key>[^=]+)=(?<value>.+)/) {|match| ENV[match[:key]] = match[:value] }
end
puts ENV['FOO']
这里的一些技巧env -i
在没有任何环境变量的情况下执行命令( -c
)。 我尝试使用此技巧, 如何在Ruby脚本中为命令外壳提供环境变量? 但是set
给您所有的环境变量,我只想要那个文件中的那些。
吉姆的想法很好,但由于我的限制而无法使用。 CodeGnome在正确的路径上,但是如果不进行评估就无法批发阅读文件,否则我们会误认为file = Pathname.new "tmp-variables.txt"
。 谢谢大家,这是团队的共同努力。 我已经给你们所有人投票了。
您可以使用dotenv gem导入.env文件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.