How Have Both Local and Remote Variable Inside an Ssh Command

How have both local and remote variable inside an SSH command

I think this is what you want:

A=3;
ssh host@name "B=3; echo $A; echo \$B;"

When you use double-quotes:

Your shell does auto expansion on variables prefixed with $, so in your first example, when it sees

ssh host@name "B=3; echo $A; echo $B;"

bash expands it to:

ssh host@name "B=3; echo 3; echo ;"

and then passes host@name "B=3; echo 3; echo ;" as the argument to ssh. This is because you defined A with A=3, but you never defined B, so $B resolves to the empty string locally.


When you use single-quotes:

Everything enclosed by single-quotes are interpreted as string-literals, so when you do:

ssh host@name 'B=3; echo $A; echo $B;'

the instructions B=3; echo $A; echo $B; will be run once you log in to the remote server. You've defined B in the remote shell, but you never told it what A is, so $A will resolve to the empty string.


So when you use \$, as in the solution:

\$ means to interpret the $ character literally, so we send literally echo $B as one of the instructions to execute remotely, instead of having bash expand $B locally first. What we end up telling ssh to do is equivalent to this:

ssh host@name 'B=3; echo 3; echo $B;'

How to pass variable inside the ssh command inside for loop

try this one: (centos 8 test passed)

D=/tmp/test/ && for i in `ssh xxx@xxxxx "find $D -name '*.so'"`;do echo $i;done

Unable to use local and remote variables within a heredoc or command over SSH

You need to escape the $ sign if you don't want the variable to be expanded:

$ x=abc
$ bash <<EOF
> x=def
> echo $x # This expands x before sending it to bash. Bash will see only "echo abc"
> echo \$x # This lets bash perform the expansion. Bash will see "echo $x"
> EOF
abc
def

So in your case:

ssh user@host bash << EOF
# run script with output...
REMOTE_PID=$(cat $FILE_NAME)
echo \$REMOTE_PID
EOF

Or alternatively you can just use a herestring with single quotes:

$ x=abc
$ bash <<< '
> x=def
> echo $x # This will not expand, because we are inside single quotes
> '
def

Passing variables in remote ssh command

If you use

ssh pvt@192.168.1.133 "~/tools/run_pvt.pl $BUILD_NUMBER"

instead of

ssh pvt@192.168.1.133 '~/tools/run_pvt.pl $BUILD_NUMBER'

your shell will interpolate the $BUILD_NUMBER before sending the command string to the remote host.

How to pass local variable to remote using ssh and bash script?

The variable assignment TEST="sdfsd" given in the here document is no real variable assignment, i. e. the variable assignment will actually not be performed directly in the declaration / definition of the here document (but later when the here document gets evaluated by a shell).

In addition, the $TEST variable contained in an unescaped or unquoted here document will be expanded by the local shell before the local shell executes the ssh command.
The result is that $TEST will get resolved to the empty string if it is not defined in the local shell before the ssh command or the here document respectively.

As a result, the variable assignment export TEST="sdfsd" in the here document will not take effect in the local shell, but first be sent to the shell of the remote host and only there be expanded, hence your prints nothing experience.

The solution is to use an escaped or single-quoted here document, <<\EOF or <<'EOF'; or only escape the \$TEST variable in the here document; or just define the $TEST variable before the ssh command (and here document).

# prints sdfsd
export TEST="sdfsd"
ssh localhost 'bash -s' << EOF
echo $TEST
EOF

# prints sdfsd
ssh localhost 'bash -s' << EOF
export TEST="sdfsd"
echo \$TEST
EOF

# prints sdfsd
ssh localhost 'bash -s' <<'EOF'
export TEST="sdfsd"
echo $TEST
EOF

How to pass local variables to ssh scope in bash script?

The problem has nothing to do with ssh but is only related to here documents in bash or any other Posix shell.

Man page for bash says in the here document paragraph:

The format of here-documents is:

<<[-]word

here-document

delimiter

No parameter expansion, command substitution, arithmetic expansion, or pathname expansion is performed on word. If any characters in word are quoted, the delimiter is the result of quote removal on word, and the lines in the here-document are not expanded. If word is unquoted, all lines of the here-document are subjected to parameter expansion, command substitution, and arithmetic expansion. In the latter case, the character sequence \<newline> is ignored, and \ must be used to quote the characters \, $, and ` .

As you quote EOF, you explicitely ask the shell not to replace the $1 and $2 variables.

The most robust way is to not quote EOF and consistently quote all others special characters in the here document.

For example, if your here document contained something like:

ssh -T user@servername << 'EOF'
for f in /var/log/messages*
do echo "Filename: " $f
done
EOF

you could rewrite it with no quotes around EOF but with one inside $:

ssh -T user@servername << EOF
for f in /var/log/messages*
do echo "Filename: " \$f
done
EOF

That way all unquoted varibles would be interpolated.


Alternatively, if the server allows it, you can try to pass the 2 parameters as environment variables.

Say you want to use the names PARAM1 and PARAM2. The sshd_config file on the server should contain the line AcceptEnv PARAM1 PARAM2 because by default and for security reasons no environment variable is accepted.

You can then use:

export PARAM1=$1
export PARAM2=$2
ssh -T -o SendEnv=PARAM1 -o SenEnv=PARAM2 user@servername << 'EOF'
...
Using variables $PARAM1 and $PARAM2
...
EOF

ssh remote variable assignment?

Given this invocation:

ssh user@remote.server "k=5; echo $k;"

the local shell is expanding $k (which most likely isn't set) before it is executing ssh .... So the command that actually gets passed to the remote shell once the connection is made is k=5; echo ; (or k=5; echo something_else_entirely; if k is actually set locally).

To avoid this, escape the dollar sign like this:

ssh user@remote.server "k=5; echo \$k;"

Alternatively, use single quotes instead of double quotes to prevent the local expansion. However, while that would work on this simple example, you may actually want local expansion of some variables in the command that gets sent to the remote side, so the backslash-escaping is probably the better route.

For future reference, you can also type set -x in your shell to echo the actual commands that are being executed as a help for troubleshooting.

Executing multiple commands with ssh, including evaluation of environment variables on the remote machine

Just escape the $ using \.

ssh my_user@my_host "echo \$USER; echo \$HOSTNAME"


Related Topics



Leave a reply



Submit