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
delimiterNo 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
Unix: How to Delete Files Listed in a File
What Do the Numbers in /Proc/Loadavg Mean on Linux
Cannot Connect to X Server :0.0 with a Qt Application
Perl Command Line Multi-Line Replace
Apache Not Accepting Incoming Connections from Outside of Localhost
Bash: Inserting a Line in a File at a Specific Location
Is There an Invalid Pthread_T Id
How to Get Position of Cursor in Terminal
Sending a Mail from a Linux Shell Script
What's the Purpose of Each of the Different Uids a Process Can Have
Perf_Event_Open - How to Monitoring Multiple Events
Syntax Error Near Unexpected Token 'Then'
Limitations of Intel Assembly Syntax Compared to At&T
Difference Between Arm-Eabi Arm-Gnueabi and Gnueabi-Hf Compilers
Gcloud Compute Copy-Files': Permission Denied When Copying Files
When to Check for Eintr and Repeat the Function Call
How to Get the Difference (Only Additions) Between Two Files in Linux