Consider this:
$ ssh localhost bash -c 'export foo=bar'
terdon@localhost's password:
declare -x DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/1000/bus"
declare -x HOME="/home/terdon"
declare -x LOGNAME="terdon"
declare -x MAIL="/var/spool/mail/terdon"
declare -x OLDPWD
declare -x PATH="/usr/bin:/bin:/usr/sbin:/sbin"
declare -x PWD="/home/terdon"
declare -x SHELL="/bin/bash"
declare -x SHLVL="2"
declare -x SSH_CLIENT="::1 55858 22"
declare -x SSH_CONNECTION="::1 55858 ::1 22"
declare -x USER="terdon"
declare -x XDG_RUNTIME_DIR="/run/user/1000"
declare -x XDG_SESSION_ID="c5"
declare -x _="/usr/bin/bash"
Why does exporting a variable within a bash -c
session run via ssh result in that list of declare -x
commands (the list of currently exported variables, as far as I can tell)?
Running the same thing without the bash -c
doesn't do that:
$ ssh localhost 'export foo=bar'
terdon@localhost's password:
$
Nor does it happen if we don't export
:
$ ssh localhost bash -c 'foo=bar'
terdon@localhost's password:
$
I tested this by sshing from one Ubuntu machine to another (both running bash 4.3.11) and on an Arch machine, sshing to itself as shown above (bash version 4.4.5).
What's going on here? Why does exporting a variable inside a bash -c
call produce this output?
Best Answer
When you run a command through
ssh
, it is run by calling your$SHELL
with the-c
flag:So,
ssh remote_host "bash -c foo"
will actually run:Now, because the command you are running (
export foo=bar
) contains spaces and is not properly quoted to form a whole, theexport
is taken as the command to be run and the rest are saved in the positional parameters array. This means thatexport
is run andfoo=bar
is passed to it as$0
. The final result is the same as runningThe correct command would be: