Bash script placing quotes around command - bash

I have a Bash script that will get an IP to use as part of an SSH tunnel, but running this script the SSH tunnel fails. When using set -x I can see it places the arguments to the SSH command in single quotes and manually running this line results in the same error.
The Script:
ssh -N -L 9000:${ip_array[$2]}:443 ssh-server
The first argument is used elsewhere in the script for something else which is why the second is used here. ssh-server is an alias in my SSH config to the server i am tunneling through.
The output I get is:
ssh -N -L '9000:"172.0.0.1":443' ssh-server
Could this be because the script to fetch the IP returns strings to the array?

you can try removing the double-quotes first :
ip=$(echo "${ip_array[$2]}" | sed "s/\"//g")
ssh -N -L 9000:${ip}:443 ssh-server

Or just use shell parameter expansion to remove the quotes:
ssh -N -L 9000:${ip_array[$2]//"/}:443 ssh-server
That lone double quote may mess up your editor's syntax highlighting.

Get rid of the quotes by piping it through the tr command:
ssh -N -L 9000:$( echo ${ip_array[$2]} | tr -d '"' ):443 ssh-server

Related

ssh bash with whitespace?

Can anyone explain, please, why this command echoes an empty line instead of "abc"? I'm stuck with this. I know there are multiple ways of reaching the same goal but please also explain why this command does not print "abc" and why it's wrong.
ssh 127.0.0.1 bash -c "echo abc"
You effectively lose a level of quoting when you execute commands via ssh. You would need to write instead:
ssh 127.0.0.1 'bash -c "echo abc"'
Without those outside quotes, the command you're running on the remote system is:
bash -c echo abc
Here you're running the command echo, with $0 set to abc.

Testing boolean condition with grep on a remote host in a bash script

In a shell script I'm writing, I want to check whether a file on a remote host contains the word "open".
From the command line, I can do this successfully using
ssh user#remote_host 'grep "open" remote/folder/file'
When I was testing this in a local folder, the following worked:
if grep -q "open" local/folder/file; then
echo ...
I'm not sure how to format the conditional using ssh, though. Double quotes? Brackets? Just putting the above ssh command (which works from the command line) into brackets doesn't work:
if [ ssh user#remote_host 'grep -q "open" remote/folder/file' ]; then ...
All pointers appreciated.

Write SSH command over multiple lines

I'm trying to remote login to a shell and execute a bunch of commands on the shell.
But to make it more readable, I'd like to place my code over multiple lines. How should I be doing this?
ssh -o <Option> -x -l <user> <host> " $long_command1; $long_command2; .... "
Thanks!
ssh is in fact just passing a string to the remote host. There this string is given to a shell which is supposed to interpret it (the user's login shell, which is typically something like bash). So whatever you want to execute needs to be interpretable by that remote login shell, that's the whole rule you have to stick to.
You can indeed just use newlines within the command string:
ssh alfe#sweethome "
ls /home/alfe/whatever
ping foreignhost
date
rm foobar
"
You can use the Here Documents feature of bash.
It is like:
ssh <remote-host> bash <<EOF
echo first command
echo second command
EOF
EOF marks the end of the input.
For further info: use man bash and search for Here Documents.
Edit: The only caveat is that using variables can be tricky, you have to escape the $ to protect them to be evaluated on the remote host rather then the local shell. Like \$HOSTNAME. Otherwise works with everything that is run from bash and uses stdin.
You can do like in the following example.
ssh -o <Option> -x -l <user> <host> '
pwd
whoami
ls
echo "$PATH"
'

Deleting word from line on remote server

I am trying to delete a word from bash profile on remote server but the command never come out.
ssh -X test_server 'sed -e \'s/unalias ls//g\' -i .bash_profile' </dev/null
Not sure what i am doing wrong, Kindly assist.
It's not possible to nest single quotes in shell, switching to double quotes should give you the desired result. E.g.:
$ ssh somehost sh <<< 'echo "Xunalias lsX" | sed -e "s/unalias ls//"'
XX

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