MySQL dump CronJob - mysql

I'm trying to create a cron that daily backups my MySQL slave. The backup.sh content:
#!/bin/bash
#
# Backup mysql from slave
#
#
sudo mysql -u root -p'xxxxx' -e 'STOP SLAVE SQL_THREAD;'
sudo mysqldump -u root -p'xxxxx' ng_player | gzip > database_`date +\%Y-\%m-\%d`.sql.gz
sudo mysqladmin -u root -p'xxxxx' start-slave
I made it executable by sudo chmod +x /home/dev/backup.sh
and entered in to crontab by:
sudo crontab -e
0 12 * * * /home/dev/backup.sh
but it doesn't work, if I only run in the command line it works but not in crontab.
FIXED:
I used the script from this link: mysqldump doesn't work in crontab

Break the problem in half. First try sending only email from the cron job to see if you are getting it to even run. Put this above in a file and have your cron job point to it:
#!/bin/bash
/bin/mail -s "test subject" "yourname#yourdomain" < /dev/null
The good thing about using this tester is that it is very simple and more likely to give you some results. It does not depend on your current working directory, which can sometimes be not what you expect it to be.

Try use full link to mysql bin directory in .sh file
example :
sudo /var/lib/mysql -u root -p'xxxxx' -e 'STOP SLAVE SQL_THREAD;'

I had this same problem.
I figured out that you can't use the command sudo in a non-interactive script.
The sudo command would create a field where you would type in the password to your account (root).
If you are logged into a command prompt like ssh sudo works without typing in any passwords, but when another program runs sudo it would ask for password.
Try this instead su command doesn't require any logins and it does the same thing.
su --session-command="mysql -u root -p'xxxxx' -e 'STOP SLAVE SQL_THREAD;'" root
su --session-command="mysqldump -u root -p'xxxxx' ng_player | gzip > database_`date +\%Y-\%m-\%d`.sql.gz" root
su --session-command="mysqladmin -u root -p'xxxxx' start-slave" root
Replace root with your linux username.
EDIT:
Look at this thread for a different answer.
https://askubuntu.com/questions/173924/how-to-run-cron-job-using-sudo-command

Let's start with the silly stuff in the script.
The only command which you don't run via 'sudo' is the, spookily enough, only command which I would expect you might need to run via sudo (depending on the permissions of the target file).
Prefixing the commands in a script with sudo without a named user (i.e. running as root) serves no useful function if you are invoking the script as root.
On a typical installation, the mysql, mysqladmin and gzip programs are typically executable by any user - the authentication and authorization of the commands to the DBMS are authenticated by the DBMS using the authentication credentials passed as arguments - hence I would not expect that any of the operations here, except possibly writing to the output file (depending on its permissions).
You don't specify a path for the backup file - maybe it's writing it somewhere other than you expect?
(similarly, you should check if any of the executables are in a location which is not in the $PATH for the crontab execution environment).
but it doesn't work
....is not an error message.
The output of any command run via cron is mailed to the owner of the crontab - go read your mail.

Related

Issue with mysqldump returning Permission denied

I'm trying to setup a backup system for MySQL from PHP by using mysqldump command but I'm having a Permission denied error.
I'm on MacOS Catalina 10.15.6, using system PHP and Homebrew mysql#57.
After many attempts, I could reproduce this issue in Terminal. If I run the command as me, it works fine and the backup file is correctly created, but when I run it as _www I get the error.
This works:
% mysqldump --defaults-extra-file="crd" --extended-insert mydb > backup.sql.gz
And this does not work:
% sudo -u _www mysqldump --defaults-extra-file="crd" --extended-insert mydb > backup.sql.gz
sudo: unable to execute /usr/local/opt/mysql#5.7/bin/mysqldump: Permission denied
I checked and mysqldump can be executed by user, group and other:
% ls -la /usr/local/opt/mysql#5.7/bin | grep mysqldump
-r-xr-xr-x 1 jbogdani staff 3853364 Aug 17 21:22 mysqldump
Other attempts to provide username and password in the command also fail.
mysqldump will need a password for the mysql user root. If you don't supply that password it won't work, sudo or no sudo.
instead of using sudo -u _www just execute it with current mysql user account.
if you need further reading
You need to use a full path on the output.
You do not have permissions to write to /usr/local/opt/mysql#5.7/bin/backup.sql.gz. Specify full path of the target backup archive to another directory
I think you'll find the _www user is restricted in some way. It might not have a valid shell, it might be locked, or there might be apparmour/selinux restrictions preventing it from running.
Check the output of dmesg and /var/log/secure for useful logs, otherwise check and change the shell and status of the user using usermod to find and isolate the issue.
Make sure you consider the security ramifications before doing anything in production though.

Automate mysql_secure_installation with echo command via a shell script

I am trying to automate mysql_secure_installation script with automated response. My code is as follows :
echo "& y y abc abc y y y y" | ./usr/bin/mysql_secure_installation
The actual questions which i am automating are as follows:
Enter current password for root (enter for none): <enter>
Set root password? [Y/n] y
New password: abc
Re-enter new password: abc
Remove anonymous users? [Y/n] y
Disallow root login remotely? [Y/n] y
Remove test database and access to it? [Y/n] y
Reload privilege tables now? [Y/n] y
But it gives me an error "Sorry you cannot use an empty password here" but in the screen i used to press the return key for the first question.
I stumbled upon this question but decided to run the queries manually through a Bash script:
#!/bin/bash
# Make sure that NOBODY can access the server without a password
mysql -e "UPDATE mysql.user SET Password = PASSWORD('CHANGEME') WHERE User = 'root'"
# Kill the anonymous users
mysql -e "DROP USER ''#'localhost'"
# Because our hostname varies we'll use some Bash magic here.
mysql -e "DROP USER ''#'$(hostname)'"
# Kill off the demo database
mysql -e "DROP DATABASE test"
# Make our changes take effect
mysql -e "FLUSH PRIVILEGES"
# Any subsequent tries to run queries this way will get access denied because lack of usr/pwd param
Since mysql_secure_installation is just a Bash script, just check out the raw source code as shown here. Look for the lines that read, do_query (note that extra space I placed after do_query; need to find queries versus the function) and then you can find these commands.
UPDATE mysql.user SET Password=PASSWORD('root') WHERE User='root';
DELETE FROM mysql.user WHERE User='';
DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');
DROP DATABASE IF EXISTS test;
DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';
FLUSH PRIVILEGES;
Note that for this example, I have the password being set to root but feel free to change that to match your setup needs. Anyway, take that simply pile of MySQL commands and save it in a file named mysql_secure_installation.sql.
With that done, just run the following command via script to secure the MySQL install:
mysql -sfu root < "mysql_secure_installation.sql"
The s silences errors and the f forces the commands to continue even if one chokes. The u relates to the username that immediately follows it which—in this case—is clearly root.
Run that in a deployment script where MySQL is installed initially without a password and you are all set to lock it down without any keyboard interaction.
PS: This script was put together to secure a MySQL installation on Ubuntu 14.04 which was installed with the export DEBIAN_FRONTEND=noninteractive set and the actual install command being set to sudo -E aptitude install -y --assume-yes -q mysql-server mysql-client. Doing that will cleanly install MySQL on Ubuntu without a password; which is nice for deployment scripts. This mysql -sfu root < "mysql_secure_installation.sql" just locks it all down in seconds after that install happens.
I just did this on CentOS 6.7 with the following:
mysql_secure_installation <<EOF
y
secret
secret
y
y
y
y
EOF
You can try to use expect, that automates interactive applications.
Look at this automating mysql_secure_installation or at my modification.
Here is an automated script for a fresh MySQL 5.7 installation based on #Giacomo1968's answer. Works fine on CentOS 7.5.1804.
yum localinstall -y https://dev.mysql.com/get/mysql57-community-release-el7-9.noarch.rpm
yum install -y mysql-community-server
# start mysql service
service mysqld start
# get Temporary root Password
root_temp_pass=$(grep 'A temporary password' /var/log/mysqld.log |tail -1 |awk '{split($0,a,": "); print a[2]}')
echo "root_temp_pass:"$root_temp_pass
# mysql_secure_installation.sql
cat > mysql_secure_installation.sql << EOF
# Make sure that NOBODY can access the server without a password
UPDATE mysql.user SET Password=PASSWORD('yourrootpass') WHERE User='root';
# Kill the anonymous users
DELETE FROM mysql.user WHERE User='';
# disallow remote login for root
DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');
# Kill off the demo database
DROP DATABASE IF EXISTS test;
DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';
# Make our changes take effect
FLUSH PRIVILEGES;
EOF
mysql -uroot -p"$root_temp_pass" --connect-expired-password <mysql_secure_installation.sql
sudo mysql -e "SET PASSWORD FOR root#localhost = PASSWORD('123');FLUSH PRIVILEGES;"
printf "123\n n\n n\n n\n y\n y\n y\n" | sudo mysql_secure_installation
Enter current password for root (enter for none)? (I have 123 set for root)
Switch to unix_socket authentication? n
Change the root password? n
Remove anonymous users? n
Disallow root login remotely? y
Remove test database and access to it? y
Reload privilege tables now? y
Version:
mysql Ver 15.1 Distrib 10.4.6-MariaDB, for osx10.14 (x86_64) using readline 5.1
It's not necessary to use expect or to fish the SQL commands out of the source code (although if you want to, the C++ file you are looking for is here: https://github.com/mysql/mysql-server/blob/7ed30a748964c009d4909cb8b4b22036ebdef239/client/mysql_secure_installation.cc)
If you are happy with the defaults in mysql_secure_installation (the most secure option is always the default) then you can use the --use-default option to skip most of the interaction. mysql_secure_installation will still ask you for a root password interactively if one is not set, so you can just script that away by setting it before calling mysql_secure_option.
Here's an example:
mysql -u root <<EOF
SET PASSWORD FOR root#localhost = '${ROOT_PASSWORD}';
FLUSH PRIVILEGES;
EOF
mysql_secure_installation -u root --password="${ROOT_PASSWORD}" --use-default
I had the same problem.
Replacing the echo command to use -e and \n seems to have fixed it.
echo -e "\ny\ny\nabc\nabc\ny\ny\ny\ny\n" | ./usr/bin/mysql_secure_installation
Works for AWS. Amazon Linux 2 AMI.
Custom settings to start an instance (AWS User data):
#!/bin/bash
sudo yum -y update &> /dev/null
wget https://repo.mysql.com/mysql80-community-release-el7-1.noarch.rpm &> /dev/null
sudo yum -y localinstall mysql80-community-release-el7-1.noarch.rpm
sudo yum -y install mysql-community-server &> /dev/null
sudo service mysqld start
# get Temporary root Password
root_temp_pass=$(sudo grep 'A temporary password' /var/log/mysqld.log |tail -1 |awk '{split($0,a,": "); print a[2]}')
echo "root_temp_pass: " $root_temp_pass
# mysql_secure_installation.sql
sudo cat > mysql_secure_installation.sql << EOF
# Make sure that NOBODY can access the server without a password
ALTER USER 'root'#'localhost' IDENTIFIED BY 'yourrootpass';
# Kill the anonymous users
DELETE FROM mysql.user WHERE User='';
# disallow remote login for root
DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');
# Kill off the demo database
DROP DATABASE IF EXISTS test;
DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';
# Make our changes take effect
FLUSH PRIVILEGES;
EOF
sudo mysql -uroot -p"$root_temp_pass" --connect-expired-password <mysql_secure_installation.sql
sudo systemctl enable mysql
You could try this:
echo -e "\ny\ny\nabc\nabc\ny\ny\ny\ny" | ./usr/bin/mysql_secure_installation
Just tested this on Ubuntu Bionic 18.04LTS
Step #1
export MYPWD="D33Ps3CR3T";
export NEWPWD="D33P3Rs3CR3T";
Step #2
# First time **ever**
sudo mysql_secure_installation 2>/dev/null <<MSI
n
y
${MYPWD}
${MYPWD}
y
y
y
y
MSI
# Did it work?
mysql -u root -p${MYPWD} -e "SELECT 1+1";
# -------
Step #3
# Every subsequent time
sudo mysql_secure_installation 2>/dev/null <<MSI2
${MYPWD}
n
y
${NEWPWD}
${NEWPWD}
y
y
y
y
MSI2
# Just in case (optional) ....
sudo service mysql restart
# Did it work?
mysql -u root -p${NEWPWD} -e "SELECT 1+1";
You should be able to cut'n paste steps #2 & #3 directly into a terminal, after editing the before and after passwords from step #1.
Notes
If a root password has already been set step #2 will fail, so go to step #3
It's just a heredoc fed into the command
sudo is obligatory.
MSI has no particular meaning (it's collision avoidance; I use EOF elsewhere in the script)
MYPWD == NEWPWD is allowed
2>/dev/null hides the warning "stty: 'standard input': Inappropriate ioctl for device"
You can use &>/dev/null for fully silent mode.
I am using simple command to change root password after MySql installation ,But getting the Above error (signal 9 kill)
(FATAL: Chef::Exceptions::ChildConvergeError: Chef run process terminated by signal 9 (KILL)) Though the command works and password is changed the error is confusing.
script "change password" do
interpreter "bash"
user "root"
cwd "/tmp"
code <<-EOH
#MYSQL
root_temp_pass=$(grep 'A temporary password' /mysql/log/mysqld.log |tail -1 |awk '{split($0,a,": "); print a[2]}')
#Login as root change password
mysql -uroot -p"$root_temp_pass" -Be "ALTER USER 'root'#'localhost' IDENTIFIED BY 'Czt732ck#';" --connect-expired-password
EOH
end
I use following lines. Works fine for AWS Linux AMI 2018
db_root_password=Password4root
cat <<EOF | mysql_secure_installation
y
0
$db_root_password
$db_root_password
y
y
y
y
y
EOF
The top-voted solution is a bit of a hack, and is version, spin, and OS specific. Unfortunately the elegant solution (using --use-defaults) is not supported by the script shipped with RHEL9.
Here is a somewhat more compatible hack to extract the correct commands from the shipped script:
grep 'do_query ' /usr/bin/mariadb-secure-installation | \
sed -e 's/ *do_query \"//' -e 's/\"$//' \
-e "s/\$esc_pass/$db_admin_pass/" \
-e 's/([^;])$/\\1;/' | \
grep -v 'show create' | \
mysql --user=$db_admin_user
The first 2 sed commands strip off the do_query call from each SQL command.
The second line sets your new root password.
The third line adds a trailing semicolon to any SQL commands not so terminated; this is broken in the script shipped with RHEL9
The command assumes you provide the variables $db_admin_user and $db_admin_pass
The code was pulled from my puppet manifest so command quoting may differ depending on how you use it.
The mysql command needs root privileges (which it should inherit from your automation engine)
echo -e "${MARIADB_ROOT_PASSWORD}\nY\nn\nY\nn\nY\nY\n" | ./usr/bin/mysql_secure_installation
...did work for me, in my mariadb docker container. Without this call I could not get simple things like /etc/init.d/mariadb status running.
In Windows OS just search for 'mysql_secure_installation' application usually found in Drive:\MySQL_Install-DIR\bin\
By pressing WindowKey + R just run the command 'Drive:\MySQL_Install-DIR\bin\mysql_secure_installation'
When you run this command a window will pop up that will walk you through the process of securing your MySQL installation. That's it!

mysqldump doesn't work in crontab

I'm trying to add a cronjob in the crontab (ubuntu server) that backups the mysql db.
Executing the script in the terminal as root works well, but inserted in the crontab nothing happens. I've tried to run it each minutes but no files appears in the folder /var/db_backups.
(Other cronjobs work well)
Here is the cronjob:
* * * * * mysqldump -u root -pHERE THERE IS MY PASSWORD
--all-databases | gzip > /var/db_backups/database_`date +%d%m%y`.sql.gz
what can be the problem?
You need to escape % character with \
mysqldump -u 'username' -p'password' DBNAME > /home/eric/db_backup/liveDB_`date +\%Y\%m\%d_\%H\%M`.sql
I was trying the same but I found that dump was created with 0KB. Hence, I got to know about the solution which saved my time.
Command :
0 0 * * * mysqldump -u 'USERNAME' -p'PASSWORD' DATEBASE > /root/liveDB_`date +\%Y\%m\%d_\%H\%M\%S`.sql
NOTE:
1) You can change the time setting as per your requirement. I have set every day in above command.
2) Make sure you enter your USERNAME, PASSWORD, and DATABASE inside single quote (').
3) Write down above command in Crontab.
I hope this helps someone.
Check cron logs (should be in /var/log/syslog) You can use grep to filter them out.
grep CRON /var/log/syslog
Also you can check your local mail box to see if there are any cron mails
/var/mail/username
You can also set up other receiving mail in you crontab file
MAILTO=your#mail.com
Alternatively you can create a custom command mycommand. To which you can add more options. You must give execute permissions.
It is preferable to have a folder where they store all your backups, in this case using a writable folder "backup" which first create in "your home" for example.
My command in "usr/local/bin/mycommand":
#!/bin/bash
MY_USER="your_user"
MY_PASSWORD="your_pass"
MY_HOME="your_home"
case $1 in
"backupall")
cd $MY_HOME/backup
mysqldump --opt --password=$MY_PASSWORD --user=$MY_USER --all-databases > bckp_all_$(date +%d%m%y).sql
tar -zcvf bckp_all_$(date +%d%m%y).tgz bckp_all_$(date +%d%m%y).sql
rm bckp_all_$(date +%d%m%y).sql;;
*) echo "Others";;
esac
Cron: Runs the 1st day of each month.
0 0 1 * * /usr/local/bin/mycommand backupall
I hope it helps somewhat.
Ok, I had a similar problem and was able to get it fixed.
In your case you could insert that mysqldump command to a script
then source the profile of the user who is executing the mysqldump command
for eg:
. /home/bla/.bash_profile
then use the absolute path of the mysqldump command
/usr/local/mysql/bin/mysqldump -u root -pHERE THERE IS MY PASSWORD --all-databases | gzip > /var/db_backups/database_`date +%d%m%y`.sql.gz
Local Host mysql Backup:
0 1 * * * /usr/local/mysql/bin/mysqldump -uroot -ppassword --opt database > /path/to/directory/filename.sql
(There is no space between the -p and password or -u and username - replace root with a correct database username.)
It works for me. no space between the -p and password or -u and username
Create a new file and exec the code there to dump into a file location and zip it . Run that script via a cron
I am using Percona Server (a MySQL fork) on Ubuntu. The package (very likely the regular MySQL package as well) comes with a maintenance account called debian-sys-maint. In order for this account to be used, the credentials are created when installing the package; and they are stored in /etc/mysql/debian.cnf.
And now the surprise: A symlink /root/.my.cnf pointing to /etc/mysql/debian.cnf gets installed as well.
This file is an option file read automatically when using mysql or mysqldump. So basically you then had login credentials given twice - in that file and on command line. This was the problem I had.
So one solution to avoid this condition is to use --no-defaults option for mysqldump. The option file then won't be read. However, you provide credentials via command line, so anyone who can issue a ps can actually see the password once the backup runs. So it's best if you create an own option file with user name and password and pass this to mysqldump via --defaults-file.
You can create the option file by using mysql_config_editor or simply in any editor.
Running mysqldump via sudo from the command line as root works, just because sudo usually does not change $HOME, so .my.cnf is not found then. When running as a cronjob, it is.
You might also need to restart the service to load any of your changes.
service cron restart
or
/etc/init.d/cron restart

Setting mysql as shell

I have a user on my machine that is only supposed to run mysql. Is there any way that I can set the shell of that user to mysql and login using password and username?
I know how to change the shell to the mysql binary
usermod -s /usr/bin/mysql
That is working indeed, only I can't provide a username/password in the program. Usually user/pw are given as
mysql -u $USER -p
I can not provide parameters for a shell as in
usermod -s "/usr/bin/mysql -u $USER -p" # Does not work!
Also using a simple shell-script as shell does not work:
#!/bin/sh # mysqlShell
/usr/bin/mysql -u $USER -p
----
usermod -s mysqlShell # does not work
So how can I provide parameters to a program I use as a shell for a user?
Thanks to Tom Regner I could figure out a solution using .my.cnf containing
[client]
host=localhost
user=$user
password=$pass
disable-auto-rehash
where mysql is set to the shell. I still would like give the password manually but this is the best I found.
Setup a $HOME/.my.cnf file for the user
[client]
host=localhost
user=mysqluser
password=mysqlpass
then set a bash as login shell and put the following in $HOME/.bashrc
exec mysql --host=localhost dbname
that should do what you want, while the user in question just has to give one password (the system account password on login).
exec replaces the shell process with the mysql process.
If this does not work as expected, you may need to adjust $HOME/.bash_profile to source .bashrc:
[[ -f ~/.bashrc ]] && . ~/.bashrc
It might be enough to provide an appropriate .my.cnf and setting /usr/bin/mysql as shell, but this way you can pass arbitrary commandline options/flags to the mysql client.
You can do that by editing the user's account details in the /etc/passwd and change the default shell.
You need a login password (unless you set up ssh appropriately). Use the following command: sudo passwd username to change that login password.
You also need a mysql password. Use SET PASSWORD Mysql request.
If you want the user to be connected to some fixed database with some fixed password, code a small C wrapper (then, make the executable only executable by your Unix user) doing mysql_real_connect, or calling some exec function for mysql --user=username --password=password databasename but I don't recommend doiing the later (because ps aux will show the password, and that is a security risk).
Perhaps, since MySQL is free software, you could customize the source code of mysql for your particular needs.
Perhaps using a restricted shell and carefully configuring it is better.

How to perform a mysqldump without a password prompt?

I would like to know the command to perform a mysqldump of a database without the prompt for the password.
REASON:
I would like to run a cron job, which takes a mysqldump of the database once everyday. Therefore, I won't be able to insert the password when prompted.
How could I solve this ?
Since you are using Ubuntu, all you need to do is just to add a file in your home directory and it will disable the mysqldump password prompting. This is done by creating the file ~/.my.cnf (permissions need to be 600).
Add this to the .my.cnf file
[mysqldump]
user=mysqluser
password=secret
This lets you connect as a MySQL user who requires a password without having to actually enter the password. You don't even need the -p or --password.
Very handy for scripting mysql & mysqldump commands.
The steps to achieve this can be found in this link.
Alternatively, you could use the following command:
mysqldump -u [user name] -p[password] [database name] > [dump file]
but be aware that it is inherently insecure, as the entire command (including password) can be viewed by any other user on the system while the dump is running, with a simple ps ax command.
Adding to #Frankline's answer:
The -p option must be excluded from the command in order to use the password in the config file.
Correct:
mysqldump –u my_username my_db > my_db.sql
Wrong:
mysqldump –u my_username -p my_db > my_db.sql
.my.cnf can omit the username.
[mysqldump]
password=my_password
If your .my.cnf file is not in a default location and mysqldump doesn't see it, specify it using --defaults-file.
mysqldump --defaults-file=/path-to-file/.my.cnf –u my_username my_db > my_db.sql
A few answers mention putting the password in a configuration file.
Alternatively, from your script you can export MYSQL_PWD=yourverysecretpassword.
The upside of this method over using a configuration file is that you do not need a separate configuration file to keep in sync with your script. You only have the script to maintain.
There is no downside to this method.
The password is not visible to other users on the system (it would be visible if it is on the command line). The environment variables are only visible to the user running the mysql command, and root.
The password will also be visible to anyone who can read the script itself, so make sure the script itself is protected. This is in no way different than protecting a configuration file. You can still source the password from a separate file if you want to have the script publicly readable (export MYSQL_PWD=$(cat /root/mysql_password) for example). It is still easier to export a variable than to build a configuration file.
E.g.,
$ export MYSQL_PWD=$(>&2 read -s -p "Input password (will not echo): "; echo "$REPLY")
$ mysqldump -u root mysql | head
-- MySQL dump 10.13 Distrib 5.6.23, for Linux (x86_64)
--
-- Host: localhost Database: mysql
-- ------------------------------------------------------
-- Server version 5.6.23
/*!40101 SET #OLD_CHARACTER_SET_CLIENT=##CHARACTER_SET_CLIENT */;
/*!40101 SET #OLD_CHARACTER_SET_RESULTS=##CHARACTER_SET_RESULTS */;
/*!40101 SET #OLD_COLLATION_CONNECTION=##COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
MariaDB
MariaDB documents the use of MYSQL_PWD as:
Default password when connecting to mysqld. It is strongly recommended to use a more secure method of sending the password to the server.
The page has no mentions of what a "more secure" method may be.
MySQL
This method is still supported in the latest documented version of MySQL: https://dev.mysql.com/doc/refman/8.0/en/environment-variables.html though it comes with the following warning:
Use of MYSQL_PWD to specify a MySQL password must be considered extremely insecure and should not be used. Some versions of ps include an option to display the environment of running processes. On some systems, if you set MYSQL_PWD, your password is exposed to any other user who runs ps. Even on systems without such a version of ps, it is unwise to assume that there are no other methods by which users can examine process environments.
The security of environment variables is covered in much details at https://security.stackexchange.com/a/14009/10002 and this answer also addresses the concerns mentioned in the comments. TL;DR Irrelevant for over a decade.
Having said that, the MySQL documentation also warns:
MYSQL_PWD is deprecated as of MySQL 8.0; expect it to be removed in a future version of MySQL.
To which I'll leave you with maxschlepzig's comment from below:
funny though how Oracle doesn't deprecate passing the password on the command line which in fact is extremely insecure
Final thoughts
Connecting to a system using a single factor of authentication (password) is indeed insecure. If you are worried about security, you should consider adding mutual TLS on top of the regular connection so both the server and the client are properly identified as being authorized.
To use a file that is anywhere inside of OS, use --defaults-extra-file eg:
mysqldump --defaults-extra-file=/path/.sqlpwd [database] > [desiredoutput].sql
Note: .sqlpwd is just an example filename. You can use whatever you desire.
Note: MySQL will automatically check for ~/.my.cnf which can be used instead of --defaults-extra-file
If your using CRON like me, try this!
mysqldump --defaults-extra-file=/path/.sqlpwd [database] > "$(date '+%F').sql"
Required Permission and Recommended Ownership
sudo chmod 600 /path/.sqlpwd && sudo chown $USER:nogroup /path/.sqlpwd
.sqlpwd contents:
[mysqldump]
user=username
password=password
Other examples to pass in .cnf or .sqlpwd
[mysql]
user=username
password=password
[mysqldiff]
user=username
password=password
[client]
user=username
password=password
If you wanted to log into a database automatically, you would need the [mysql] entry for instance.
You could now make an alias that auto connects you to DB
alias whateveryouwant="mysql --defaults-extra-file=/path/.sqlpwd [database]"
You can also only put the password inside .sqlpwd and pass the username via the script/cli. I'm not sure if this would improve security or not, that would be a different question all-together.
For completeness sake I will state you can do the following, but is extremely insecure and should never be used in a production environment:
mysqldump -u [user_name] -p[password] [database] > [desiredoutput].sql
Note: There is NO SPACE between -p and the password.
Eg -pPassWord is correct while -p Password is incorrect.
Yeah it is very easy .... just in one magical command line no more
mysqldump --user='myusername' --password='mypassword' -h MyUrlOrIPAddress databasename > myfile.sql
and done :)
For me, using MariaDB I had to do this: Add the file ~/.my.cnf and change permissions by doing chmod 600 ~/.my.cnf. Then add your credentials to the file. The magic piece I was missing was that the password needs to be under the client block (ref: docs), like so:
[client]
password = "my_password"
[mysqldump]
user = root
host = localhost
If you happen to come here looking for how to do a mysqldump with MariaDB. Place the password under a [client] block, and then the user under a [mysqldump] block.
You can achieve this in 4 easy steps
create directory to store script and DB_backups
create ~/.my.cnf
create a ~/.script.sh shell script to run the mysqldump
Add a cronjob to run the mysql dump.
Below are the detailed steps
Step 1
create a directory on your home directory using sudo mkdir ~/backup
Step 2
In your home directory run sudo nano ~/.my.cnf and add the text below and save
[mysqldump]
#use this if your password has special characters (!##$%^&..etc) in it
password="YourPasswordWithSpecialCharactersInIt"
#use this if it has no special characters
password=myPassword
Step 3
cd into ~/backup and create another file script.sh
add the following text to it
SQLFILE=/path/to/where/you/want/to/dump/dbname.sql
DATABASE=dbname
USER=myUsername
mysqldump --defaults-file=~/.my.cnf -u ${USER} ${DATABASE}|gzip > dbName_$(date +\%Y\%m\%d_\%H\%M).sql.gz
Step 4
In your console, type crontab -e to open up the cron file where the auto-backup job will be executed from
add the text below to the bottom of the file
0 0 * * * ./backup/script.sh
The text added to the bottom of the cron file assumes that your back up shall run daily at midnight.
That's all you need folk
;)
Here is a solution for Docker in a script /bin/sh :
docker exec [MYSQL_CONTAINER_NAME] sh -c 'exec echo "[client]" > /root/mysql-credentials.cnf'
docker exec [MYSQL_CONTAINER_NAME] sh -c 'exec echo "user=root" >> /root/mysql-credentials.cnf'
docker exec [MYSQL_CONTAINER_NAME] sh -c 'exec echo "password=$MYSQL_ROOT_PASSWORD" >> /root/mysql-credentials.cnf'
docker exec [MYSQL_CONTAINER_NAME] sh -c 'exec mysqldump --defaults-extra-file=/root/mysql-credentials.cnf --all-databases'
Replace [MYSQL_CONTAINER_NAME] and be sure that the environment variable MYSQL_ROOT_PASSWORD is set in your container.
Hope it will help you like it could help me !
Check your password!
Took me a while to notice that I was not using the correct user name and password in ~/.my.cnf
Check the user/pass basics before adding in extra options to crontab backup entries
If specifying --defaults-extra-file in mysqldump then this has to be the first option
A cron job works fine with .my.cnf in the home folder so there is no need to specify --defaults-extra-file
If using mysqlpump (not mysqldump) amend .my.cnf accordingly
The ~/.my.cnf needs permissions set so only the owner has read/write access with:
chmod 600 ~/.my.cnf
Here is an example .my.cnf:
[mysql]
host = localhost
port = 3306
user = BACKUP_USER
password = CORRECTBATTERYHORSESTAPLE
[mysqldump]
host = localhost
port = 3306
user = BACKUP_USER
password = CORRECTBATTERYHORSESTAPLE
[mysqlpump]
host = localhost
port = 3306
user = BACKUP_USER
password = CORRECTBATTERYHORSESTAPLE
The host and port entries are not required for localhost
If your user name in linux is the same name as used for your backup purposes then user is not required
Another tip, whilst you are doing a cronjob entry for mysqldump is that you can set it to be a low priority task with ionice -c 3 nice 19. Combined with the --single-transaction option for InnoDB you can run backups that will not lock tables or lock out resources that might be needed elsewhere.
I have the following.
/etc/mysqlpwd
[mysql]
user=root
password=password
With the following alias.
alias 'mysql -p'='mysql --defaults-extra-file=/etc/mysqlpwd'
To do a restore I simply use:
mysql -p [database] [file.sql]
This is how I'm backing-up a MariaDB database using an expanding variable.
I'm using a "secrets" file in a Docker-Compose setup to keep passwords out of Git, so I just cat that in an expanding variable in the script.
NOTE: The below command is executed from the Docker host itself:
mysqldump -h192.168.1.2 -p"$(cat /docker-compose-directory/mariadb_root_password.txt)" -uroot DB-Name > /backupsDir/DB-Name_`date +%Y%m%d-%H:%M:%S`.sql
This is tested and known to work correctly in Ubuntu 20.04 LTS with mariadb-client.
I'm doing mine a different way, using Plink(Putty command line) to connect to remotehost, then the below command is in the plink file that runs on the remote server, then I use RSYNC from windows to get it and backup to an onprem NAS.
sudo mysqldump -u root --all-databases --events --routines --single-transaction > dump.sql
I have keys setup on the remote host and using PowerShell that's scheduled via task scheduler to run weekly.
what about --password=""
worked for me running on 5.1.51
mysqldump -h localhost -u <user> --password="<password>"
Definitely I think it would be better and safer to place the full cmd line in the root crontab , with credentails.
At least the crontab edit is restricred (readable) to someone who already knows the password.. so no worries to show it in plain text...
If needed more than a simple mysqldump... just place a bash script that accepts credentails as params and performs all amenities inside...
The bas file in simple
#!/bin/bash
mysqldump -u$1 -p$2 yourdbname > /your/path/save.sql
In the Crontab:
0 0 * * * bash /path/to/above/bash/file.sh root secretpwd 2>&1 /var/log/mycustomMysqlDump.log
You can specify the password on the command line as follows:
mysqldump -h <host> -u <user> -p<password> dumpfile
The options for mysqldump are Case Sensitive!