Passing variables (environment variables) over ssh
is possible but generally restricted.
You need to tell the client to send them. For instance with OpenSSH, that's with:
ssh -o SendEnv=parameter host cmd...
But you also need the server to accept it (AcceptEnv
configuration directive with OpenSSH). Accepting any variable is a big security risk so is generally not done by default, though some ssh deployments allow some variables under some namespace (like LC_*
in some OpenSSH deployments).
You also need to export the variable before calling ssh
, like:
LC_parameter="$parameter" ssh -o SendEnv=LC_parameter host csh << 'END'
echo $LC_parameter:q
END
Above, we're passing the content of the $parameter
bash
shell variable as the LC_parameter
environment variable to ssh
. ssh
sends that over to sshd
, which if it accepts it, passes it as an environment variable to the login shell of the user which then passes it to that csh
command (which can then expand it).
But as mentioned earlier, that won't work unless the administrator of the host
machine has added a AcceptEnv LC_parameter
or AcceptEnv LC_*
(that one sometimes done by default) to the sshd
configuration.
The Undefined variable
error message in your example suggests the login shell of the remote user is csh
or tcsh
. It's better to explicitly invoke the shell to avoid surprises (ssh host csh
also means a tty is not requested so you don't need -T
). Note the $LC_parameter:q
syntax, which is the csh
way to pass the content of a variable verbatim, not "$LC_parameter"
which doesn't work if the variable contains newline characters.
If using LC_*
variables is not an option, then alternatively, you can have the client shell (bash
in your case) expand the variable. A naive way would be with
ssh host csh << END
echo "$variable"
END
But that would be dangerous as the content of the variable would be interpreted by the remote shell. If $variable
contains `reboot`
or "; reboot; : "
for instance, that would have bad consequences.
So, you'd need first to make sure the variable is properly quoted in the syntax of the remote shell. Here, I would avoid csh
where it's hard to do reliably and use sh
/bash
/ksh
instead.
Use a helper function to do the sh quoting:
shquote() {
awk -v q=\' -v b='\\' '
BEGIN{
for (i=1; i<ARGC; i++) {
gsub(q, q b q q, ARGV[i])
printf "%s ", q ARGV[i] q
}
print ""
exit
}' "$@"
}
And call ssh
as:
ssh host sh << END
parameter=$(shquote "$parameter")
echo "\$parameter"
END
See how we escape the third $
so the expansion of $parameter
is done by the remote shell, not the local one.