Skip to content

Commit

Permalink
Export environment variables and execute command in a subshell
Browse files Browse the repository at this point in the history
  • Loading branch information
kuon committed Aug 13, 2015
1 parent fa0b9c6 commit 3a10fe4
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 11 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ appear at the top.

* Add your entries below here, remember to credit yourself however you want
to be credited!
* Export environment variables and execute command in a subshell.
[PR #272](https://github.com/capistrano/sshkit/pull/272)
@kuon
* Introduce `log_command_start`, `log_command_data`, `log_command_exit` methods on `Formatter`
[PR #257](https://github.com/capistrano/sshkit/pull/257)
@robd
Expand Down
2 changes: 1 addition & 1 deletion lib/sshkit/command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ def environment_string

def with(&block)
return yield unless environment_hash.any?
"( #{environment_string} %s )" % yield
"( export #{environment_string} ; %s )" % yield
end

def user(&block)
Expand Down
12 changes: 11 additions & 1 deletion test/functional/backends/test_netssh.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def test_simple_netssh
Command: /usr/bin/env ls -l
Command: if test ! -d /tmp; then echo \"Directory does not exist '/tmp'\" 1>&2; false; fi
Command: if ! sudo -u root whoami > /dev/null; then echo \"You cannot switch to user 'root' using sudo, please check the sudoers file\" 1>&2; false; fi
Command: cd /tmp && ( RAILS_ENV="production" sudo -u root RAILS_ENV="production" -- sh -c '/usr/bin/env touch restart.txt' )
Command: cd /tmp && ( export RAILS_ENV="production" ; sudo -u root RAILS_ENV="production" -- sh -c '/usr/bin/env touch restart.txt' )
EOEXPECTED
end

Expand All @@ -62,6 +62,16 @@ def test_ssh_option_merge
assert_equal({ forward_agent: false, paranoid: true }, host_ssh_options)
end

def test_env_vars_substituion_in_subshell
captured_command_result = nil
Netssh.new(a_host) do |host|
with some_env_var: :some_value do
captured_command_result = capture(:echo, '$SOME_ENV_VAR')
end
end.run
assert_equal "some_value", captured_command_result
end

def test_execute_raises_on_non_zero_exit_status_and_captures_stdout_and_stderr
err = assert_raises SSHKit::Command::Failed do
Netssh.new(a_host) do |host|
Expand Down
18 changes: 9 additions & 9 deletions test/unit/test_command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,44 +28,44 @@ def test_using_a_heredoc
def test_including_the_env
SSHKit.config = nil
c = Command.new(:rails, 'server', env: {rails_env: :production})
assert_equal %{( RAILS_ENV="production" /usr/bin/env rails server )}, c.to_command
assert_equal %{( export RAILS_ENV="production" ; /usr/bin/env rails server )}, c.to_command
end

def test_including_the_env_with_multiple_keys
SSHKit.config = nil
c = Command.new(:rails, 'server', env: {rails_env: :production, foo: 'bar'})
assert_equal %{( RAILS_ENV="production" FOO="bar" /usr/bin/env rails server )}, c.to_command
assert_equal %{( export RAILS_ENV="production" FOO="bar" ; /usr/bin/env rails server )}, c.to_command
end

def test_including_the_env_with_string_keys
SSHKit.config = nil
c = Command.new(:rails, 'server', env: {'FACTER_env' => :production, foo: 'bar'})
assert_equal %{( FACTER_env="production" FOO="bar" /usr/bin/env rails server )}, c.to_command
assert_equal %{( export FACTER_env="production" FOO="bar" ; /usr/bin/env rails server )}, c.to_command
end

def test_double_quotes_are_escaped_in_env
SSHKit.config = nil
c = Command.new(:rails, 'server', env: {foo: 'asdf"hjkl'})
assert_equal %{( FOO="asdf\\\"hjkl" /usr/bin/env rails server )}, c.to_command
assert_equal %{( export FOO="asdf\\\"hjkl" ; /usr/bin/env rails server )}, c.to_command
end

def test_including_the_env_doesnt_addressively_escape
SSHKit.config = nil
c = Command.new(:rails, 'server', env: {path: '/example:$PATH'})
assert_equal %{( PATH="/example:$PATH" /usr/bin/env rails server )}, c.to_command
assert_equal %{( export PATH="/example:$PATH" ; /usr/bin/env rails server )}, c.to_command
end

def test_global_env
SSHKit.config = nil
SSHKit.config.default_env = { default: 'env' }
c = Command.new(:rails, 'server', env: {})
assert_equal %{( DEFAULT="env" /usr/bin/env rails server )}, c.to_command
assert_equal %{( export DEFAULT="env" ; /usr/bin/env rails server )}, c.to_command
end

def test_default_env_is_overwritten_with_locally_defined
SSHKit.config.default_env = { foo: 'bar', over: 'under' }
c = Command.new(:rails, 'server', env: { over: 'write'})
assert_equal %{( FOO="bar" OVER="write" /usr/bin/env rails server )}, c.to_command
assert_equal %{( export FOO="bar" OVER="write" ; /usr/bin/env rails server )}, c.to_command
end

def test_working_in_a_given_directory
Expand All @@ -75,7 +75,7 @@ def test_working_in_a_given_directory

def test_working_in_a_given_directory_with_env
c = Command.new(:ls, '-l', in: "/opt/sites", env: {a: :b})
assert_equal %{cd /opt/sites && ( A="b" /usr/bin/env ls -l )}, c.to_command
assert_equal %{cd /opt/sites && ( export A="b" ; /usr/bin/env ls -l )}, c.to_command
end

def test_having_a_host_passed
Expand Down Expand Up @@ -120,7 +120,7 @@ def test_umask_with_working_directory_and_user
def test_umask_with_env_and_working_directory_and_user
SSHKit.config.umask = '007'
c = Command.new(:touch, 'somefile', user: 'bob', env: {a: 'b'}, in: '/var')
assert_equal %{cd /var && umask 007 && ( A="b" sudo -u bob A="b" -- sh -c '/usr/bin/env touch somefile' )}, c.to_command
assert_equal %{cd /var && umask 007 && ( export A="b" ; sudo -u bob A="b" -- sh -c '/usr/bin/env touch somefile' )}, c.to_command
end

def test_verbosity_defaults_to_logger_info
Expand Down

0 comments on commit 3a10fe4

Please sign in to comment.