我正在使用 chef-solo 在 Windows 上自动进行一些配置。我有一个需要通过以前的配方间接设置环境的配方的问题(具体来说,我在配方 1 中安装了 Visual Studio,配方 2 需要在新环境中启动才能访问由配方 1 设置的变量)。
据我所知,没有办法告诉厨师“重新加载环境”?实现这一目标的最佳方法是什么?更糟糕的是,如果这样做更容易,我也不介意重新启动,只要重新启动和厨师继续供应是完全自动化的。
我正在使用 chef-solo 在 Windows 上自动进行一些配置。我有一个需要通过以前的配方间接设置环境的配方的问题(具体来说,我在配方 1 中安装了 Visual Studio,配方 2 需要在新环境中启动才能访问由配方 1 设置的变量)。
据我所知,没有办法告诉厨师“重新加载环境”?实现这一目标的最佳方法是什么?更糟糕的是,如果这样做更容易,我也不介意重新启动,只要重新启动和厨师继续供应是完全自动化的。
您可以运行一个 ruby 块并将新的环境变量添加到当前环境变量中:
ruby_block "get new env variables" do
block do
new_env = `cmd.exe /C set`
#do some parsing magic, then set the new_env
ENV = parsed_env
end
end
我没有对此进行测试,但它可能会让你走上正轨。
Chocolatey 使用Refreshenv
脚本完成相同的任务,从注册表重新加载环境变量。
我已将此脚本移植到 Ruby(在 Apache 2.0 许可下获得许可):
require 'win32/registry'
def get_reg_env(hkey, subkey, &block)
Win32::Registry.open(hkey, subkey) do |reg|
reg.each_value do |name|
value = reg.read_s_expand(name)
if block && ENV.key?(name)
ENV[name] = block.call(name, ENV[name], value)
else
ENV[name] = value
end
end
end
end
def refresh_env
get_reg_env(Win32::Registry::HKEY_LOCAL_MACHINE, 'System\CurrentControlSet\Control\Session Manager\Environment')
get_reg_env(Win32::Registry::HKEY_CURRENT_USER, 'Environment') do |name, old_value, new_value|
if name.upcase == 'PATH'
old_value || File::PATH_SEPARATOR || new_value
else
new_value
end
end
end
你把它放在libraries
dir 中并在这样的配方中使用它:
ruby_block 'refreshenv' do
block do
refresh_env
end
action :nothing
end
chocolatey_package 'visualstudio2017buildtools' do
notifies :run, 'ruby_block[refreshenv]', :immediately
end
也许有人可以把它包在食谱里。
如需更多跨平台方式,您还可以查看dotenv gem。