diff --git a/lib/vagrant/action/builtin/ssh_run.rb b/lib/vagrant/action/builtin/ssh_run.rb index 6b411f334..3572507a8 100644 --- a/lib/vagrant/action/builtin/ssh_run.rb +++ b/lib/vagrant/action/builtin/ssh_run.rb @@ -37,13 +37,17 @@ module Vagrant # Get the command and wrap it in a login shell command = ShellQuote.escape(env[:ssh_run_command], "'") - # This will always default to 'bash -l' unless it is explicitly set in - # the Vagrantfile, because the base SSHConfig object has already been - # finalized. - shell = env[:machine].config.ssh.shell + if env[:machine].config.vm.communicator == :winssh + shell = env[:machine].config.winssh.shell + else + shell = env[:machine].config.ssh.shell + end - if env[:machine].config.vm.communicator == :winssh && shell == "cmd" - command = "#{shell} /C #{command}" + if shell == "cmd" + # Add an extra space to the command so cmd.exe quoting works + # properly + command = "#{shell} /C #{command} " + env[:tty] = false else command = "#{shell} -c '#{command}'" end diff --git a/test/unit/vagrant/action/builtin/ssh_run_test.rb b/test/unit/vagrant/action/builtin/ssh_run_test.rb index b053cf06e..39a51aaf1 100644 --- a/test/unit/vagrant/action/builtin/ssh_run_test.rb +++ b/test/unit/vagrant/action/builtin/ssh_run_test.rb @@ -88,14 +88,34 @@ describe Vagrant::Action::Builtin::SSHRun do end context "when using the WinSSH communicator" do + let(:winssh) { double("winssh", shell: "foo") } + before do expect(vm).to receive(:communicator).and_return(:winssh) - expect(ssh).to receive(:shell).and_return("cmd") + expect(config).to receive(:winssh).and_return(winssh) end - it "should use Windows-specific flags for cmd" do + it "should use the WinSSH shell for running ssh commands" do ssh_info = { foo: :bar } - opts = {:extra_args=>["-t", "cmd /C dir"], :subprocess=>true} + opts = {:extra_args=>["-t", "foo -c 'dir'"], :subprocess=>true} + + expect(ssh_klass).to receive(:exec). + with(ssh_info, opts) + + env[:ssh_info] = ssh_info + env[:ssh_run_command] = "dir" + described_class.new(app, env).call(env) + end + end + + context "when shell is cmd" do + before do + expect(ssh).to receive(:shell).and_return('cmd') + end + + it "should use appropriate options for cmd" do + ssh_info = { foo: :bar } + opts = {:extra_args=>["cmd /C dir "], :subprocess=>true} expect(ssh_klass).to receive(:exec). with(ssh_info, opts)