Passing quoted variables in remote ssh command - linux

I want to grep through a few files for a string. In this example I want to grep for "test 1234"
#!/bin/bash
variable="test 1234"
ssh root#server "grep "$variable" /path/*"
This script doesn't work because test 1234 is passed to the server instead of "test 1234"
How can I fix this?

You need to escape the quotes around $variable in your command:
ssh root#server "grep \"$variable\" /path/*"
As it stands, the variable is expanding but because the quotes aren't escaped, the command is searching for the text test in the files 1234 and /path/*

You should be able to escape the double quotes with a \ backslash character.
see escape double quote in grep

Related

Bash escape character

I have this very reduced example of a bash command, where I want the $ sign escaped.
So the command :
su -m user -c "echo $test"
should print out:
$test
a simple \$test does not work unfortunately. I tried lots of other stuff but still couldn't find a solution. Any suggestions ?
Put it in single quotes rather than double quotes.
su -m user -c 'echo \$test='
The single quotes keep the variable from being expanded by the original shell. The backslash then escapes the dollar sign in the shell run by su.
See Difference between single and double quotes in Bash
In answer to the comment, you can switch to double quoting to get single quotes into the string.
su -m user -c 'echo \$test='"'1'"

Print single quotes in shell script using option -c [duplicate]

This question already has answers here:
How to escape single quotes within single quoted strings
(25 answers)
Closed 5 years ago.
This may sound novice but I tried everything to get this to work.
I want to print a word with single quotes : 'John' in shell script. I cant replace /bin/bash -l -c as this part of code is run by Java and I have to pass the shell command as a string. I tried with echo -e option as well.
/bin/bash -l -c 'echo "'John'"'
The output I want is:
'John'
I tried escaping the single quotes but nothing helped so far. Any ideas?
You can't nest single quotes in bash, so the line is interpreted as
/bin/bash -l -c 'echo "'John'"'
|......| ---------- single quoted
|....| ----- not quoted
|.| --- quoted
So, properly escape the single quotes:
/bin/bash -c 'echo "'\''John'\''"'
or, if the string in single quotes is really simple,
/bin/bash -c 'echo "'\'John\''"'
Try removing the double quotes and escaping the single quotes:
/bin/bash -l -c "echo \'John\'"
A common workaround is to use printf so you don't need to use literal single quotes in the format string.
bash -l -c 'printf "\x27John\x27\n"'
(Using bash -l here is probably misdirected and nonportable.)

Remote SSH : no such file or directory

When trying to run this cmd:
ssh user#host " cp -f /path1/`cat /path2/file.txt | awk -F : '{printf $4}' `* ../ "
got this:
cat: /path2/file.txt: no such file or directory
Notice that when execute it directly in the server it works
Thanks for any advice
Try this:
ssh user#host 'cp -f /path1/$(awk -F : '\''{printf $4}'\'' /path2/file.txt)* ..'
This might be also interesting: Useless Use of Cat Award.
Or this:
ssh user#host 'cp -f '\'"$path1"\''/$(awk -F : '\''{printf $4}'\'' /path2/file.txt)* ..'
Keep in mind:
Singe quotes do not evaluate $.
Double quotes do evaluate $.
If you want to put a single quote into a single quoted string, you have to split the string in two parts and put an escaped single quote in between. 'a'\''b' becomes a'b
If you need to evaluate a variable in a single quoted string, you have to split the string in two parts and put the double quoted variable in between. 'a'"$x"'b' becomes a${x}b

bash escape exclamation character inside variable with backtick

I have this bash script:
databases=`mysql -h$DBHOST -u$DBUSER -p$DBPASSWORD -e "SHOW DATABASES;" | tr -d "| " | grep -v Database`
and the issue is when the password has all the characters possible. how can i escape the $DBPASSWORD in this case? If I have a password with '!' and given the fact that command is inside backticks. I have no experience in bash scripts but I've tried with "$DBPASSWORD" and with '$DBPASSWORD' and it doesn't work. Thank you
LATER EDIT: link to script here, line 170 -> https://github.com/Ardakilic/backmeup/blob/master/backmeup.sh
First: The answer from #bishop is spot on: Don't pass passwords on the command line.
Second: Use double quotes for all shell expansions. All of them. Always.
databases=$(mysql -h"$DBHOST" -u"$DBUSER" -p"$DBPASSWORD" -e "SHOW DATABASES;" | tr -d "| " | grep -v Database)
Don't pass the MySQL password on the command line. One, it can be tricky with passwords containing shell meta-characters (as you've discovered). Two, importantly, someone using ps can sniff the password.
Instead, either put the password into the system my.cnf, your user configuration file (eg .mylogin.cnf) or create an on-demand file to hold the password:
function mysql() {
local tmpfile=$(mktemp)
cat > "$tmpfile" <<EOCNF
[client]
password=$DBPASSWORD
EOCNF
mysql --defaults-extra-file="$tmpfile" -u"$DBUSER" -h"$DBHOST" "$#"
rm "$tmpfile"
}
Then you can run it as:
mysql -e "SHOW DATABASES" | tr -d "| " ....
mysql -e "SELECT * FROM table" | grep -v ...
See the MySQL docs on configuration files for further examples.
I sometimes have the same problem when automating activities:
I have a variable containing a string (usually a password) that is set in a config file or passed on the command-line, and that string includes the '!' character.
I need to pass that variable's value to another program, as a command-line argument.
If I pass the variable unquoted, or in double-quotes ("$password"), the shell tries to interpret the '!', which fails.
If I pass the variable in single quotes ('$password'), the variable isn't expanded.
One solution is to construct the full command in a variable and then use eval, for example:
#!/bin/bash
username=myuser
password='my_pass!'
cmd="/usr/bin/someprog -user '$username' -pass '$password'"
eval "$cmd"
Another solution is to write the command to a temporary file and then source the file:
#!/bin/bash
username=myuser
password='my_pass!'
cmd_tmp=$HOME/.tmp.$$
touch $cmd_tmp
chmod 600 $cmd_tmp
cat > $cmd_tmp <<END
/usr/bin/someprog -user '$username' -pass '$password'
END
source $cmd_tmp
rm -f $cmd_tmp
Using eval is simple, but writing a file allows for multiple complex commands.
P.S. Yes, I know that passing passwords on the command-line isn't secure - there is no need for more virtue-signalling comments on that topic.

Escape double quote in grep

I wanted to do grep for keywords with double quotes inside. To give a simple example:
echo "member":"time" | grep -e "member\""
That does not match. How can I fix it?
The problem is that you aren't correctly escaping the input string, try:
echo "\"member\":\"time\"" | grep -e "member\""
Alternatively, you can use unescaped double quotes within single quotes:
echo '"member":"time"' | grep -e 'member"'
It's a matter of preference which you find clearer, although the second approach prevents you from nesting your command within another set of single quotes (e.g. ssh 'cmd').

Resources