Escaping out password variable with special characters for mysqldump - mysql

I'm trying to create a shell script to automatically backup my whole database. My script expects the password in a new line because I don't want to store it anywhere. Here is my code:
#!/bin/bash
echo -n Password:
read -s PASS
echo
docker exec db /usr/bin/mysqldump --all-databases -u admin --password='\''$PASS\'' > backup-$(date "+%Y-%m-%d").sql
The problem is, that I need to put the variable into single quotes because of the $ signs in the password, but I can't read variables in single quotes.
I know there are several similar questions out there, but I could not solve is with them.
So if the password is '$ecretPa$$word', then the actual executed program should be something like this:
docker exec db /usr/bin/mysqldump --all-databases -u admin --password='$ecretPa$$word' > backup-2020-03-03.sql

I managed to make this work. Maybe the problem was not with the escaping but with the way I tried to run this.
My final code:
#!/bin/bash
echo -n Password:
read -s PASS
echo
cmd="docker exec db /usr/bin/mysqldump --all-databases -u admin --password='$PASS' > backup-$(date "+%Y-%m-%d").sql"
eval "$cmd";

Related

how to escape special characters of mariadb password in shell script

I what to write a shell script to loging in to mariadb. The shell script read one password containing special characters(blank, !#) in a ini file.
The OS is Ubuntu 18.04
the ini file as follows:
user=xxx-xxx-xxx
password=xxx /xxx /xx/ !\#
the shell script as follows:
#!/bin/bash
baseDir="$(cd "$(dirname "$0")" && pwd)"
iniPath="$baseDir/backup.ini"
echo "iniPath is $iniPath"
dbUser="$(grep 'user' $iniPath | cut -d '=' -f 2)"
echo "user is $dbUser"
dbPassword="$(grep 'password' $iniPath | cut -d '=' -f 2)"
echo "password is $dbPassword"
mysql -h localhost -u $dbUser -p'$dbPassword'
if I input the command as follows:
mysql -h localhost -u xxxxxx -p'xxx /xxx /xx/ !#'
in command line, it loging successfully.
But If I execute the shell script, it always results in accessing denied for user.
Have any suggestions? thanks.
Have you tried to use: mysql -h localhost -u $dbUser -p'echo $dbPassword' ? (special character ` is on US like keyboards under esc key left upper corner, it looks like back apostroph) Looks like the variable with password is not correctly "printed" into a mysql command before its run. Other way I would recommend trying is to use -p"$dbPassword"
FWIW, the issue is that the shell will not interpolate variables into a string surrounded by single quotes. As Honza specified, the double-quotes will work.
See Difference between single and double quotes in Bash for details.

Run mysql commands in bash script without logging in or adding -u root to every command

I'm writing a bash script to do some db stuff. New to MySQL. I'm on Mac and have MySQL installed via homebrew.
Am using username "root" right now and there isn't a pw set. I included the pw syntax below just to help others out that may have a pw.
My goal is to have mysql commands be as "clean" as possible in my bash script
Not a hige deal, but would like to do this if possible.
Example
# If I can do it without logging in (*ideal)
mysql CREATE DATABASE dbname;
# Or by logging in with - mysql -u root -pPassword
CREATE DATABASE dbname;
# Instead of
mysql -u root -pPassword -e"CREATE DATABASE dbname";
Tried to simplify it. I have a handful of things I gotta do, so would rather keep my code cleaner if possible. I tried logging in with the bash script, but the script stopped once logged into MySQL and didn't run any commands.
Another option I was considering (but don't really like) would be just to keep username and pw string in a var and call it for every commmand like so
# Set the login string variable
login_details="-u root -p password -e"
# example command
mysql $login_details"CREATE DATABASE dbname";
So any ideas?
Write a new bash script file and run this file after putting all your commands into it. Don't forget to give right username and password in your bash script.
For bash script:
#!/bin/bash
mysql -u root -pSeCrEt << EOF
use mysql;
show tables;
EOF
If you want to run single mysql command.
mysql -u [user] -p[pass] -e "[mysql commands]"
Example:
mysql -h 192.168.1.10 -u root -pSeCrEt -e "show databases"
To execute multiple mysql commands:
mysql -u $user -p$passsword -Bse "command1;command2;....;commandn"
Note: -B is for batch, print results using tab as the column separator, with each row on a new line. With this option, mysql does not use the history file. Batch mode results in nontabular output format and escaping of special characters. -s is silent mode. Produce less output. -e is to execute the statement and quit

mysqldump access denied when being used in bash script

I am trying to create a bash script that uses mysqldump to create a backup of the database that is specified as parameter. However mysqldump fails with an access denied error. Using the same command directly (copying it to the shell an executing it) works without any problem.
#!/bin/bash
# ... use parameters to get db name and password
# build the mysqldump command and execute it...
command="mysqldump -alv -h127.0.0.3 --default-character-set=utf8 -u ${database} -p'${pw}' --extended-insert ${database} | gzip > ${path}"
echo "$command"
echo ""
$command
This gives me the following output:
$ ./dbbak DBUSER DBNAME PASSWORD
mysqldump -alv -h127.0.0.3 --default-character-set=utf8 -u DBUSER -p'PASSWORD' --extended-insert DBNAME | gzip > /path/to/backup/backup.sql.gz
Warning: Using a password on the command line interface can be insecure.
-- Connecting to 127.0.0.3...
mysqldump: Got error: 1045: Access denied for user 'DBUSER'#'localhost' (using password: YES) when trying to connect
As said before: When I copy the echoed mysqldump command and execute it directly, the backup works just fine.
What is the problem here? Since the command is executed correctly when being used manually all parameters (password, username, etc.) seem to be correct. Additionally the bash script is executed with the same user account as the manual command.
So why does the manual execution work while the bash script fails?
EDIT:
As Jens pointed out in his comment, removing the quotes from the password will solve the problem. ...-p${pw}... will work, BUT this will also lead to a new problem, if the password contains special characters like $ < > ...
I assume that the problem with the quotes is how bash parses the string. Meanwhile I found some docs that say, that it is a bad habit to store commands in variables and execute them. Instead one should execute commands directly. However the following does not work as well:
result=$(mysqldump -alv -h127.0.0.3 --default-character-set=utf8 -u ${database} -p'${pw}' --extended-insert ${database} | gzip > ${path})
When executing this with bash -x dbbak the output shows the problem:
...
++ mysqldump -alv -h127.0.0.3 --default-character-set=utf8 -u DBUSER '-p'\''DBPASS'\''' --extended-insert DBNAME
While I do understand why the quotes around DBPASS are added ('DBPASS' --> \''DBPASS'\'), I do not understand why there are also quotes around-p`.
How do I get rid of these quotes when executing the command?
You can either:
store the password in an environment variable MYSQL_PWD
store the password in a plain-text file .my.cnf which you need to put into
the home directory of the user that executes the script
use the mysql_config_editor utility to store the password in an encrypted
file
The first one is the easiest to use/implement but obviously the least secure.
I recommend to take a look at the documentation where all the possibilities are described. ;)
Configure it by .cnf file and provide it in --defaults-file
mysqldump --defaults-file=~/my_mysql.cnf db table > table.sql
In ~/my_msyql.cnf
[mysqldump]
user=user_name
password=my_password
host=my_host
This is also safe if you version this. You can save my_mysql.cnf differently per environment.
To remove the single quotes around the password solved for me.

need to "build" a mysql command and exec it in a shell script

I'm new to writing shell scripts.
I am attempting to create a database using a shell script. Here's the script:
#!/bin/bash
#create a new db
a="mysql -uuser -ppassword -e'create database $1;'"
exec $a
The command exec mysql -uuser -ppassword -e'create database databaseName;' works in a shell, but when I sh the script, I get the mysql help open...
I think the problem is in the quotes, the simple quote prevent the variable expansion.
You can simply do like this in your script:
#!/bin/bash
#create a new db
mysql -u user -p password -e "create database $1;"
Or you can try to place all your mysql commands in a file, let's say "dbname.sql".
And do this:
#!/bin/bash
#create a new db
mysql -u user -p password "$1" < "$1.sql"
if you like use exec to run commands this can be a possible solution
#!/bin/bash
#create a new db
programm="mysql"
parameter[0]="-ppassword"
parameter[1]="-uuser"
parameter[2]="-ecreate database $1;"
exec "$programm" "${parameter[#]}"
exec parameter are
exec [-a NAME] [-cl] [COMMAND] [ARG...] [REDIRECTION...]
command is $programm and the array parameter is the argument list.
Sounds like you need to use the 'cat' command and a pipe instead of using 'exec' .
cat /path/to/my/file | mysql -h localhost -u root -padmin

How is the input to another command resolved in bash? How we redirect errors and pass the input?

I read the following snippet:
mysql -u $USER -p $PASS <<EOF 2> /dev/null
CREATE DATABASE students;
EOF
Ok. So this runs the mysql client and does a CREATE DATABASE.
My question is how come the 2>/dev/null is not considered part of the EOF?
I assume that the << is for the input to the program mysql after it has connected with the user and password parameters.
So how 2>/dev/null is not part of the <<?
Because words in the shell are separated by whitespace. The here-doc terminator is a word, so it does not consume the rest of the line.
http://www.gnu.org/software/bash/manual/bashref.html#Shell-Operation
Your example uses a Heredoc, and the shell ultimately interprets this as a redirection in itself. It is treated like other forms of redirection.
Equivalent Examples:
Herestring:
mysql -u $USER -p $PASS<<<"CREATE DATABASE students;" 2>/dev/null
Echo:
echo "CREATE DATABASE students;" | mysql -u $USER -p $PASS 2>/dev/null
I shamelessly recommend reading further at Greg's Wiki, because it is an excellent resource:
http://mywiki.wooledge.org/BashGuide/InputAndOutput