How to Pass Local Variable to Remote Using Ssh and Bash Script

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

In Bash script trying to pass local variable to SSH and then execute the other commands

#!/bin/bash

count2=1
declare -a input
input=( "$@" )

echo " Hostname passed by user is " "${input[0]}"
HOST="${input[0]}"

while [ $# -gt $count2 ]
do

sed -i 's/VALUE/'"${input[$count2]}"'/g' ./check.sh

sshpass -p '<pass>' scp ./check.sh user@"$HOST":/home/user/check.sh
sshpass -p '<pass>' ssh -o StrictHostKeyChecking=no user@"$HOST" "sh /home/user/check.sh && rm -rf /home/user/check.sh"

sed -i 's/'"${input[$count2]}"'/VALUE/g' ./check.sh
((count2++))

done

Found the another solution of this issue: It is working for me now !!!!

I wrote my entire logic which needs to be executed remotely in check.sh file and now replacing or storing the user input into this check.sh file and copying this file into remote server via scp and executing it over remotely and after successful execution removing this file from remote server and after ssh , again changing the user input to it's original value in local server using sed command.

Made this as dynamic script to work for multiple servers.

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.

Passing a variable to a remote host in a bash script with ssh and EOF

Use printf %q to escape content in an eval-safe form; after doing so, you can pass them on the command line of the remote shell, and retrieve them via $1, $2, etc. within the remote script:

# put contents of $VAR into $var_str in a format that a shell can interpret
printf -v var_str %q "$VAR"

# v- pass the value on the shell command line
# | v- keep escaping the heredoc securely
# | |
ssh -T -p 1234 root@"$host" "bash -s $var_str" <<'EOF'

# retrieve it off the shell command line
var=$1

# ...and use it as you like thereafter.
echo "Remotely using $var"
EOF

Passing variables in remote ssh command in shell script

This happens because you quote the here doc delimiter. Here's POSIX:

If any character in word is quoted, the delimiter is formed by performing quote removal on word, and the here-document lines will not be expanded. Otherwise, the delimiter is the word itself.

And here's an example:

#!/bin/bash
var=42

cat << 'end'
With quotes: $var and \$var
end

cat << end
Without quotes: $var and \$var
end

When executed:

With quotes: $var and \$var
Without quotes: 42 and $var


Related Topics



Leave a reply



Submit