Send a variable to a remote server with ssh - bash

Im trying to do log into a file (in a remote server lets say /home/test/log.txt) what is stored in $var. Im trying with
ssh test#$192.168.1.35 "echo "var" >> /home/test/log.txt"
y also tried
ssh test#$192.168.1.35 "echo "$var" >> log.txt"
but the both didnt work
any help?

You're using double quotes, so the variable expansion will happen locally. You should use single quotes, so that the command gets sent unaltered.
In the same way as echo '$var' gives $var while echo "$var" displays the contents, this way the server sees $var instead of the contents of the local $var.
So:
ssh test#$192.168.1.35 'echo $var >> /home/test/log.txt'
will create a file on the remote computer, with the value of the remote $var in it.
If you do
ssh test#$192.168.1.35 'echo $var' >> /home/test/log.txt
you get a file on the local computer with the value of the remote $var in it.
If you do
ssh test#$192.168.1.35 "echo $var >> /home/test/log.txt"
it stores the value of your local $var in the file on the remote system.
(Also, if it only involves the remote system, you should probably use a shell script, or maybe cron if you want it to happen automatically.)

Try:
ssh test#192.168.1.35 "echo '$var' >> /home/test/log.txt"

Did you try:
ssh test#$192.168.1.35 'echo "$var" >> /home/test/log.txt'
This should work. Assuming var was set on your computer and not the remote.

Here is the correct way to put some text from a linux machine in an already existing file on another linux machine:
echo 'text' | ssh test#$192.168.1.35 'cat >> /remote_file_path'

Related

bash returns different results when commands are passed to bash shell via ssh or HEREDOC [duplicate]

Below is an example of a ssh script using a heredoc (the actual script is more complex). Is it possible to use both local and remote variables within an SSH heredoc or command?
FILE_NAME is set on the local server to be used on the remote server. REMOTE_PID is set when running on the remote server to be used on local server. FILE_NAME is recognised in script. REMOTE_PID is not set.
If EOF is changed to 'EOF', then REMOTE_PID is set and `FILE_NAME is not. I don't understand why this is?
Is there a way in which both REMOTE_PID and FILE_NAME can be recognised?
Version 2 of bash being used. The default remote login is cshell, local script is to be bash.
FILE_NAME=/example/pdi.dat
ssh user#host bash << EOF
# run script with output...
REMOTE_PID=$(cat $FILE_NAME)
echo $REMOTE_PID
EOF
echo $REMOTE_PID
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
remote_user_name=user
instance_ip=127.0.0.1
external=$(ls /home/)
ssh -T -i ${private_key} -l ${remote_user_name} ${instance_ip} << END
internal=\$(ls /home/)
echo "\${internal}"
echo "${external}"
END

for loop over ssh getting unbound variable error

I have below syntax that would compare the modified date of xml files against f1_mdate variable.
typeset -f mdate | ssh 101.101.101.101 "cd "$tar_dir"; $(cat); for xml_file in *.xml; do mdate_xml=$(mdate $xml_file) if [[ "$f1_mdate" == "$mdate_xml" ]]; then echo 1; fi; done"
xml_file: unbound variable
mdate_xml: unbound variable
can somebody please help point out why it is getting unbound variable?
I believe the problem is quoting; this will be clearer if I put line breaks where the shell sees closing quotes:
typeset -f mdate | ssh 10.225.28.45 "cd "\
$tar_dir"; $(cat); for xml_file in *.xml; do mdate_xml=$(mdate $xml_file) if [[ "\
$f1_mdate" == "\
$mdate_xml" ]]; then echo 1; fi; done"
In terms of how to write that correctly... that gets very tricky, because you have two layers of shell which are interpreting commands, stripping quotes and interpolating variables. I usually write a small shell script, scp it to the remote machine and run that remotely, just to get around that... or use a tool like ansible.
As an example of how to get data to and from the remote machine: I created /tmp/a.sh on the remote machine foo. Here's the content of /tmp/a.sh:
while read line
do
echo "xyzzy> $line"
done
On my local machine, I have /tmp/xyz containing
foo
bar
baz
Running
cat /tmp/xyz | ssh foo bash /tmp/a.sh
will give
xyzzy> foo
xyzzy> bar
xyzzy> baz
xyzzy>
You can re-direct the output to a file:
cat /tmp/xyz | ssh foo bash /tmp/a.sh > a.txt
The file a.txt will be on your local machine.

I am unable to echo the ssh which i looge in using bash script

#!/bin/bash
read -p 'please enter the ssh server name: ' ssh_name
ssh ${ssh_name} 'bash' <<'EOF'
echo ${ssh_name}
exit
EOF
Because you put single quotes around your heredoc limit string it does not expand the variables in place, so it tries to do the variable expansion on the server side, where that variable is not set.
If you want to have the variables expanded locally, just do not use the single quotes around EOF:
read -p 'please enter the ssh server name: ' ssh_name
ssh ${ssh_name} 'bash' <<EOF
echo ${ssh_name}
exit
EOF
This will expand ssh_name on the local side then echo will see the already expanded string on the remote end and echo it.
If you want to pass that variable to the other side, you could make it part of the command you're executing:
read -p 'please enter the ssh server name: ' ssh_name
ssh ${ssh_name} remote_name="$ssh_name" 'bash' <<'EOF'
echo ${remote_name}
exit
EOF
(though you do not have to change the name of the variable, I just did that to highlight that it's available on the remote side).
here is some good reading about heredocs and herestrings.
Becuase $ssh_name is set in the shell you are calling ssh from, and you are trying to echo $ssh_name from within the ssh session itself, where it is not set.
If you move the echo statement to after the EOF or before the ssh statement, then you will find that it works just fine.

ssh bash receive variable from a remote file

I need to read the variable from a remote file over SSH and compare it. But I get a variable in the wrong format. how to do it correctly?
#!/bin/bash
pass='dpassspass'
user='root#10.10.19.18'
IP="10.2.1.41"
path=/sys/variable/serv
#not work## No such file or directory# write=$(sshpass -p $ovhpass ssh -t $user echo "$IP" > $path)
sshpass -p $pass ssh -t $user << EOF
echo "$IP" > $path
EOF
my_var=$(sshpass -p $pass ssh -t $user "cd /sys_ovh; ./serv.bash")
echo mystart-"$my_var"-myend
read=$(sshpass -p $pass ssh -t $user cat $path)
echo start-"$read"-end
echo start-"$IP"-end
if [ "$read" == "$IP" ]; then
echo "run"
fi
output:
Connection to 10.10.19.18 closed.
-myendt-10.2.1.41
Connection to 10.10.19.18 closed.
-endt-10.2.1.41
start-10.2.1.41-end
Where I make a mistake? How to take data from the SSH?
The vars my_var and read are filled with a string ending with '\r', telling echo to go back to the first column. I think this is a problem with your local script. You can correct that with
tr -d "\r" < myfile > myfile2
Your fundamental problem comes from using unquoted here documents for the commands. You should properly understand in which order the shell interprets these contructs.
ssh remote cmd >file
executes cmd remotely, but first redirects the output from the ssh command to the local file.
ssh remote "cmd >’$file'"
The quotes cause the redirection to be part of the remote command line. The variable file is interpreted first, by the local shell, though.
ssh remote 'cmd >"$file"`
The single quotes prevent the local shell from modifying the command before sending it. Thus, he variable interpolation and the redirection are both handled by the remote shell, in this order.
So your commented-out "not work" command could easily be fixed with proper quoting. However, it will be much more elegant and efficient to use a single remote session, and execute all the commands in one go. Mixing the local variable IP with remote variables calls for some rather elaborate escaping, though. A major simplification would be to pass the value on standard input, so that the entire remote script can be single quoted.
#!/bin/bash
pass='dpassspass'
user='root#10.10.19.18'
IP="10.2.1.41"
result=$(echo "$IP" |
sshpass -p "$pass" ssh -t "$user" '
path=/sys/variable/serv
cat > "$path"
cd /sys_ovh
./serv.bash
cat "$path"')
echo mystart-"${result%$'\n'*}"-myend
echo start-"${result#*$'\n'}"-end
echo start-"$IP"-end
if [ "${result#*$'\n'}" == "$IP" ]; then
echo "run"
fi
The output from the remote shell is two lines; we pick it apart by using the shell's prefix and suffix substitution operators.

Why is the order of execution inversed in this bash script?

I have this script :
ssh -T user#$123.456.789.123 <<EOF
cd www
var=$(tail index.htm)
echo $var
EOF
What I thought it should do is :
Connect to the server through SSH,
then change to the folder www,
then store the tail of index.htm into the variable var
and finally echo the result.
Instead it seems that tail is executed before the change of folder, and thus doesn't find the index.htm file.
I've tried with different commands, and each time it seems the result from command substitution I'm trying to store into a variable is executed right after the SSH connexion is opened, before any other piece of script.
What am I missing here ?
The $(...) is being expanded locally, before the contents of the here document are passed to ssh. To send literal text to the remote server, quote the here document delimiter.
ssh -T user#$123.456.789.123 <<'EOF'
cd www
var=$(tail index.htm)
echo "$var"
EOF
(Also, quote the expansion of $var to protect any embedded spacing from the shell.)
The tail is running in the bash script on your local machine, not on the remote host. The substitution is getting made before you even execute the ssh command.
Your script can be replaced with simply:
ssh -T user#$123.456.789.123 tail www/index.htm
If you want to send those commands to the remote server, you can write
ssh -T user#$123.456.789.123 'cd www && var=$(tail index.htm) && echo $var'
Note that conditioning the next command on the result of the previous allows SSH to return a meaningful return code. In your heredoc, whatever happens (e.g. tail fails), SSH will return with $?=0 because echo will not fail.
Another option is to create a script there and launch it with ssh.

Resources