Jailbreak out of the subprocess and restore original environment
This commit is contained in:
parent
46563560f4
commit
68ef9676c7
|
@ -72,31 +72,26 @@ module Vagrant
|
||||||
process.io.stderr = stderr_writer
|
process.io.stderr = stderr_writer
|
||||||
process.duplex = true
|
process.duplex = true
|
||||||
|
|
||||||
# Reset the Bundler environment back - this is required for anyone who
|
# Special installer-related things
|
||||||
# is not using the official Vagrant installers and is running Vagrant
|
if Vagrant.in_installer?
|
||||||
# via bundler
|
|
||||||
if defined?(Bundler::ORIGINAL_ENV)
|
|
||||||
Bundler::ORIGINAL_ENV.each do |k, v|
|
|
||||||
process.environment[k] = v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# If we're in an installer on Mac and we're executing a command
|
|
||||||
# in the installer context, then force DYLD_LIBRARY_PATH to look
|
|
||||||
# at our libs first.
|
|
||||||
if Vagrant.in_installer? && Platform.darwin?
|
|
||||||
installer_dir = ENV["VAGRANT_INSTALLER_EMBEDDED_DIR"].to_s.downcase
|
installer_dir = ENV["VAGRANT_INSTALLER_EMBEDDED_DIR"].to_s.downcase
|
||||||
if @command[0].downcase.include?(installer_dir)
|
|
||||||
@logger.info("Command in the installer. Specifying DYLD_LIBRARY_PATH...")
|
|
||||||
process.environment["DYLD_LIBRARY_PATH"] =
|
|
||||||
"#{installer_dir}/lib:#{ENV["DYLD_LIBRARY_PATH"]}"
|
|
||||||
else
|
|
||||||
@logger.debug("Command not in installer, not touching env vars.")
|
|
||||||
end
|
|
||||||
|
|
||||||
if File.setuid?(@command[0]) || File.setgid?(@command[0])
|
# If we're in an installer on Mac and we're executing a command
|
||||||
@logger.info("Command is setuid/setgid, clearing DYLD_LIBRARY_PATH")
|
# in the installer context, then force DYLD_LIBRARY_PATH to look
|
||||||
process.environment["DYLD_LIBRARY_PATH"] = ""
|
# at our libs first.
|
||||||
|
if Platform.darwin?
|
||||||
|
if @command[0].downcase.include?(installer_dir)
|
||||||
|
@logger.info("Command in the installer. Specifying DYLD_LIBRARY_PATH...")
|
||||||
|
process.environment["DYLD_LIBRARY_PATH"] =
|
||||||
|
"#{installer_dir}/lib:#{ENV["DYLD_LIBRARY_PATH"]}"
|
||||||
|
else
|
||||||
|
@logger.debug("Command not in installer, not touching env vars.")
|
||||||
|
end
|
||||||
|
|
||||||
|
if File.setuid?(@command[0]) || File.setgid?(@command[0])
|
||||||
|
@logger.info("Command is setuid/setgid, clearing DYLD_LIBRARY_PATH")
|
||||||
|
process.environment["DYLD_LIBRARY_PATH"] = ""
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# If the command that is being run is not inside the installer, reset
|
# If the command that is being run is not inside the installer, reset
|
||||||
|
@ -105,10 +100,10 @@ module Vagrant
|
||||||
# and $GEM_PATH for example)
|
# and $GEM_PATH for example)
|
||||||
if !@command[0].downcase.include?(installer_dir)
|
if !@command[0].downcase.include?(installer_dir)
|
||||||
@logger.info("Command not in installer, restoring original environment...")
|
@logger.info("Command not in installer, restoring original environment...")
|
||||||
Vagrant.original_env.each do |k, v|
|
jailbreak(process.environment)
|
||||||
process.environemnt[k] = v
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
jailbreak(process.environment)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Set the environment on the process if we must
|
# Set the environment on the process if we must
|
||||||
|
@ -259,6 +254,58 @@ module Vagrant
|
||||||
@stderr = stderr
|
@stderr = stderr
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# This is, quite possibly, the saddest function in all of Vagrant.
|
||||||
|
#
|
||||||
|
# If a user is running Vagrant via Bundler (but not via the official
|
||||||
|
# installer), we want to reset to the "original" environment so that when
|
||||||
|
# shelling out to other Ruby processes (specifically), the original
|
||||||
|
# environment is restored. This is super important for things like
|
||||||
|
# rbenv and chruby, who rely on environment variables to locate gems, but
|
||||||
|
# Bundler stomps on those environment variables like an angry T-Rex after
|
||||||
|
# watching Jurassic Park 2 and realizing they replaced you with CGI.
|
||||||
|
#
|
||||||
|
# If a user is running in Vagrant via the official installer, BUT trying
|
||||||
|
# to execute a subprocess *outside* of the installer, we want to reset to
|
||||||
|
# the "original" environment. In this case, the Vagrant installer actually
|
||||||
|
# knows what the original environment was and replaces it completely.
|
||||||
|
#
|
||||||
|
# Finally, we reset any Bundler-specific environment variables, since the
|
||||||
|
# subprocess being called could, itself, be Bundler. And Bundler does not
|
||||||
|
# behave very nicely in these circumstances.
|
||||||
|
#
|
||||||
|
# This function was added in Vagrant 1.7.3, but there is a failsafe
|
||||||
|
# because the author doesn't trust himself that this functionality won't
|
||||||
|
# break existing assumptions, so users can specify
|
||||||
|
# `VAGRANT_SKIP_SUBPROCESS_JAILBREAK` and none of the above will happen.
|
||||||
|
#
|
||||||
|
# This function modifies the given hash in place!
|
||||||
|
#
|
||||||
|
# @return [nil]
|
||||||
|
def jailbreak(env = {})
|
||||||
|
return if ENV.key?("VAGRANT_SKIP_SUBPROCESS_JAILBREAK")
|
||||||
|
|
||||||
|
env.replace(::Bundler::ORIGINAL_ENV) if defined?(::Bundler::ORIGINAL_ENV)
|
||||||
|
env.merge!(Vagrant.original_env)
|
||||||
|
|
||||||
|
# Bundler does this, so I guess we should as well, since I think it
|
||||||
|
# other subprocesses that use Bundler will reload it
|
||||||
|
env["MANPATH"] = ENV["BUNDLE_ORIG_MANPATH"]
|
||||||
|
|
||||||
|
# Replace all current environment BUNDLE_ variables to nil
|
||||||
|
ENV.each do |k,_|
|
||||||
|
env[k] = nil if k[0,7] == "BUNDLE_"
|
||||||
|
end
|
||||||
|
|
||||||
|
# If RUBYOPT was set, unset it with Bundler
|
||||||
|
if ENV.key?("RUBYOPT")
|
||||||
|
env["RUBYOPT"] = ENV["RUBYOPT"].sub("-rbundler/setup", "")
|
||||||
|
end
|
||||||
|
|
||||||
|
nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -90,6 +90,19 @@ Note that any `vagrant plugin` commands automatically don't load any
|
||||||
plugins, so if you do install any unstable plugins, you can always use
|
plugins, so if you do install any unstable plugins, you can always use
|
||||||
the `vagrant plugin` commands without having to worry.
|
the `vagrant plugin` commands without having to worry.
|
||||||
|
|
||||||
|
## VAGRANT\_SKIP\_SUBPROCESS\_JAILBREAK
|
||||||
|
|
||||||
|
As of Vagrant 1.7.3, Vagrant tries to intelligently detect if it is running in
|
||||||
|
the installer or running via Bundler. Although not officially supported, Vagrant
|
||||||
|
tries its best to work when executed via Bundler. When Vagrant detects that you
|
||||||
|
have spawned a subprocess that lives outside of Vagrant's installer, Vagrant
|
||||||
|
will do its best to reset the preserved environment dring the subprocess
|
||||||
|
execution.
|
||||||
|
|
||||||
|
If Vagrant detects it is running outside of the officially installer, the
|
||||||
|
original environment will always be restored. You can disable this automatic
|
||||||
|
jailbreak by setting the `VAGRANT_SKIP_SUBPROCES_JAILBREAK`.
|
||||||
|
|
||||||
## VAGRANT\_VAGRANTFILE
|
## VAGRANT\_VAGRANTFILE
|
||||||
|
|
||||||
This specifies the filename of the Vagrantfile that Vagrant searches for.
|
This specifies the filename of the Vagrantfile that Vagrant searches for.
|
||||||
|
|
Loading…
Reference in New Issue