Why does exporting a variable in an ssh shell print the list of exported variables?
When you run a command through ssh
, it is run by calling your $SHELL
with the -c
flag:
-c If the -c option is present, then commands are read from
the first non-option argument command_string. If there are
arguments after the command_string, the first argument is
assigned to $0 and any remaining arguments are assigned to
the positional parameters.
So, ssh remote_host "bash -c foo"
will actually run:
/bin/your_shell -c 'bash -c foo'
Now, because the command you are running (export foo=bar
) contains spaces and is not properly quoted to form a whole, the export
is taken as the command to be run and the rest are saved in the positional parameters array. This means that export
is run and foo=bar
is passed to it as $0
. The final result is the same as running
/bin/your_shell -c 'bash -c export'
The correct command would be:
ssh remote_host "bash -c 'export foo=bar'"
ssh
concatenates the arguments with spaces and has the login shell of the remote user interpret it, so in:
ssh localhost bash -c 'export foo=bar'
ssh
is asking the remote shell to interpret the
bash -c export foo=bar
command (in effect, if the remote host is Unix-like, it will run the remote shell with the-shell
, -c
and bash -c export foo=bar
as arguments).
Most shells will interpret that command line as running the bash
command with bash
, -c
, export
and foo=bar
as arguments (so run export
while $0
contains foo=bar
) while you'd want it to run it with bash
, -c
and export foo=bar
as arguments.
For that, you'd need to use a command line like:
ssh localhost "bash -c 'export foo=bar'"
(or:
ssh localhost bash -c \'export foo=bar\'
for that matters) so the:
bash -c 'export foo=bar'
command line be passed to the remote shell. That command line would be interpreted by most shells as running the bash
command with bash
, -c
and export foo=bar
as arguments. Note that using
ssh localhost 'bash -c "export foo=bar"'
would not work if the login shell of the remote user was rc
or es
for instance where "
is not a special quoting operator. Single quotes are the most portable quoting operators (though there is some variation on how they are interpreted between shells, see How to execute an arbitrary simple command over ssh without knowing the login shell of the remote user? for more on that).