Backup MySQL users - mysql

How do I backup MySQL users and their privileges?
Anything like mysqldump?
I am looking for something like:
mysqldump -d -u root -p MyTable > Schema.sql

mysql -BNe "select concat('\'',user,'\'#\'',host,'\'') from mysql.user where user != 'root'" | \
while read uh; do mysql -BNe "show grants for $uh" | sed 's/$/;/; s/\\\\/\\/g'; done > grants.sql

You can backup mysql database using
mysqldump -u root -p mysql > mysql.sql
and restore mysql database by executing
mysql -uroot -p mysql < mysql.sql
Dont forget to
FLUSH PRIVILEGES
after restoring dump.
Hope it helps...

So far my experience with MySQL i didn't see anything to backup user and their privileges through a command line.
But i can backup those critical data by backing up mysql
mysqldump -u root -p mysql > mysql.sql

Percona has a great tool for this. pt-show-grants will dump users and their permissions so you can easily reload them.
https://www.percona.com/doc/percona-toolkit/LATEST/pt-show-grants.html

The users and privileges are stored in the databased named 'mysql'. You can use mysqldump to backup the tables in the databased named 'mysql'.

Good practice is using script for daily backup MySQL users and their privileges.
Take take a look on a one:
#!/bin/sh
HOSTNAME="localhost"
mysql -h $HOSTNAME -B -N -e "SELECT CONCAT('\'', user,'\'#\'', host, '\'') FROM user WHERE user != 'debian-sys-maint' AND user != 'root' AND user != ''" mysql > mysql_all_users_$HOSTNAME.txt
while read line; do mysql -h $HOSTNAME -B -N -e "SHOW GRANTS FOR $line"; done < mysql_all_users_$HOSTNAME.txt > mysql_all_users_$HOSTNAME.sql
sed -i.bak 's/$/;/' mysql_all_users_$HOSTNAME.sql
rm mysql_all_users_$HOSTNAME.txt
rm mysql_all_users_$HOSTNAME.sql.bak
Result of this script will be mysqldump file with users and privileges.
P.S. If your MySQL requires password - put -p or -u username -p after mysql -h $HOSTNAME in two places.

The scripts given above give the general idea, but they're inefficient. They're forking/execing mysql n+1 times. It can be done in only two calls to mysql
mysql ${logininfo} -B -N -e "SELECT CONCAT('\'',user,'\'#\'',host,'\'') from user where user != 'root'" mysql | \
while read uh
do
echo "SHOW GRANTS FOR ${uh};"
done | mysql ${logininfo} -B -N | sed -e 's/$/;/' > ${outfile}
If there are users other than root that you don't want to backup use or and specify user != 'whatever' in the where clause of the first mysql call.

probably pretty obvious for mysql command liners but for #spirit's answer above had to add -u root -ppassword after both mysql commands
mysql -u root -ppassword -BNe "select concat(''',user,''#'',host,''') from mysql.user where user != 'root'" | while read uh; do mysql -u root -ppassword -BNe "show grants for $uh" | sed 's/$/;/; s/\\/\/g'; done > grants.sql;

Related

Backup all privileges related to specific user of MySQL

I want to backup all privileges related to specific user (for example u_1) from a MySQL database and restore that in another server. As described here, The 'mysql' database contains users/privileges/passwords. So I have to backup all related data from all tables of mysql database (mysql.user,mysql.db, ...). I can run this command:
$ mysqldump -u root --flush-privileges -r mysql.sql -p mysql
But of course the mysql.sql contains all users and all privileges.
Also I tried this command:
$ mysqldump -u root -p --where="user.user='u_1'" mysql user> mysql.sql
But as expected, it only contains a row of mysql.user table.
Is there a way to strip out other users except of u_1?
Try these options (line breaks for clarity):
$ mysqldump -u root -p
--where="user='u_1'"
--complete-insert
--extended-insert
--no-create-info
mysql
user db tables_priv columns_priv procs_priv proxies_priv
> mysql.sql
Or... let's call the above solution "the hard way."
This should be the easy way:
$ mysql -u root -p
--skip-column-names
-e "SHOW GRANTS FOR 'u_1';"
> grants.sql
I would use:
pt-show-grants --only u_1
pt-show-grants is a tool in the free Percona Toolkit.
See https://www.percona.com/doc/percona-toolkit/LATEST/pt-show-grants.html

avoid asking second time mysql root password (bash)

In a simple script like this one:
set -x
# Check if db exists, if not we make it, make user, give privileges
if ! mysql -u root -p -e "use $db" 2>/dev/null; then
c1="CREATE DATABASE $db"
c2="GRANT ALL PRIVILEGES ON ${db}.* to '$username'#'localhost' IDENTIFIED BY '$password'"
c3="FLUSH PRIVILEGES"
mysql -u root -p -e "$c1; $c2; $c3"
else
echo 'DATABASE ExISTS, ABORTING'; exit $DB_EXISTS
fi
I am asked each time, bash sees mysql command, for my root credentials.
Is there a way to avoid that, so that once entered the root password, all
additional mysql commands execute seamlessly?
Try looking into adding password to ~/.my.cnf
[client]
user = root
password = XXXXXXXX
Check out :
How to execute a MySQL command from a shell script?
Specifying the --password argument
mysql -u root --password=my_mysql_pass db_name
Safer using a bash variable
mysql -u root --password=$MYSQL_PASS db_name

mysqldump command in linux till date(I mean i dont want to dump changes in the database that i made today)

Normally we Dump data in such manner:
What i require is i just want to dump data till yesterday !!!
mysqldump -u root -p gateway > dumpfilename.sql
You can pass -e parameter with query that should be executed:
mysqldump -u root -p troy22022012 -e "SELECT * FROM gateway WHERE ..." > dumpfilename.sql

Copy mysql database from remote server to local computer

I'm under VPN and I don't have SSH access to remote server.
I can connect to remote database by console
mysql -u username -p -h remote.site.com
Now I'm trying to clone the remote database to local computer
mysqldump -u username -p -h remote.site.com mysqldump | mysql -u root -ppassword webstuff
And I've got error
mysqldump: Got error: 1045: Access denied for user 'webstaff'#'10.75.1.2'
(using password: YES) when trying to connect
How to copy mysql database from remote server to local computer?
Assuming the following command works successfully:
mysql -u username -p -h remote.site.com
The syntax for mysqldump is identical, and outputs the database dump to stdout. Redirect the output to a local file on the computer:
mysqldump -u username -p -h remote.site.com DBNAME > backup.sql
Replace DBNAME with the name of the database you'd like to download to your computer.
Check syntax and execute one command at a time, then verify output.
mysqldump -u remoteusername -p remotepassword -h your.site.com databasename > dump.sql
mysql -u localusername -p localpassword databasename < dump.sql
Once you've matched all passwords, you can use pipe.
Often our databases are really big and the take time to take dump directly from remote machine to other machine as our friends other have suggested above.
In such cases what you can do is to take the dump on remote machine using MYSQLDUMP Command
MYSQLDUMP -uuser -p --all-databases > file_name.sql
and than transfer that file from remote server to your machine using Linux SCP Command
scp user#remote_ip:~/mysql_dump_file_name.sql ./
This can have different reasons like:
You are using an incorrect password
The MySQL server got an error when trying to resolve the IP address of the client host to a name
No privileges are granted to the user
You can try one of the following steps:
To reset the password for the remote user by:
SET PASSWORD FOR some_user#ip_addr_of_remote_client=PASSWORD('some_password');
To grant access to the user by:
GRANT SELECT, INSERT, UPDATE, DELETE, LOCK TABLES ON YourDB.* TO user#Host IDENTIFIED by 'password';
Hope this helps you, if not then you will have to go through the documentation
Please check this gist.
https://gist.github.com/ecdundar/789660d830d6d40b6c90
#!/bin/bash
# copymysql.sh
# GENERATED WITH USING ARTUR BODERA S SCRIPT
# Source script at: https://gist.github.com/2215200
MYSQLDUMP="/usr/bin/mysqldump"
MYSQL="/usr/bin/mysql"
REMOTESERVERIP=""
REMOTESERVERUSER=""
REMOTESERVERPASSWORD=""
REMOTECONNECTIONSTR="-h ${REMOTESERVERIP} -u ${REMOTESERVERUSER} --password=${REMOTESERVERPASSWORD} "
LOCALSERVERIP=""
LOCALSERVERUSER=""
LOCALSERVERPASSWORD=""
LOCALCONNECTION="-h ${LOCALSERVERIP} -u ${LOCALSERVERUSER} --password=${LOCALSERVERPASSWORD} "
IGNOREVIEWS=""
MYVIEWS=""
IGNOREDATABASES="select schema_name from information_schema.SCHEMATA where schema_name != 'information_schema' and schema_name != 'mysql' and schema_name != 'performance_schema' ;"
# GET A LIST OF DATABASES
databases=`$MYSQL $REMOTECONNECTIONSTR -e "${IGNOREDATABASES}" | tr -d "| " | grep -v schema_name`
# COPY ALL TABLES
for db in $databases; do
# GET LIST OF ITEMS
views=`$MYSQL $REMOTECONNECTIONSTR --batch -N -e "select table_name from information_schema.tables where table_type='VIEW' and table_schema='$db';"
IGNOREVIEWS=""
for view in $views; do
IGNOREVIEWS=${IGNOREVIEWS}" --ignore-table=$db.$view "
done
echo "TABLES "$db
$MYSQL $LOCALCONNECTION --batch -N -e "create database $db; "
$MYSQLDUMP $REMOTECONNECTIONSTR $IGNOREVIEWS --compress --quick --extended-insert --skip-add-locks --skip-comments --skip-disable-keys --default-character-set=latin1 --skip-triggers --single-transaction $db | mysql $LOCALCONNECTION $db
done
# COPY ALL PROCEDURES
for db in $databases; do
echo "PROCEDURES "$db
#PROCEDURES
$MYSQLDUMP $REMOTECONNECTIONSTR --compress --quick --routines --no-create-info --no-data --no-create-db --skip-opt --skip-triggers $db | \
sed -r 's/DEFINER=`[^`]+`#`[^`]+`/DEFINER=CURRENT_USER/g' | mysql $LOCALCONNECTION $db
done
# COPY ALL TRIGGERS
for db in $databases; do
echo "TRIGGERS "$db
#TRIGGERS
$MYSQLDUMP $REMOTECONNECTIONSTR --compress --quick --no-create-info --no-data --no-create-db --skip-opt --triggers $db | \
sed -r 's/DEFINER=`[^`]+`#`[^`]+`/DEFINER=CURRENT_USER/g' | mysql $LOCALCONNECTION $db
done
# COPY ALL VIEWS
for db in $databases; do
# GET LIST OF ITEMS
views=`$MYSQL $REMOTECONNECTIONSTR --batch -N -e "select table_name from information_schema.tables where table_type='VIEW' and table_schema='$db';"`
MYVIEWS=""
for view in $views; do
MYVIEWS=${MYVIEWS}" "$view" "
done
echo "VIEWS "$db
if [ -n "$MYVIEWS" ]; then
#VIEWS
$MYSQLDUMP $REMOTECONNECTIONSTR --compress --quick -Q -f --no-data --skip-comments --skip-triggers --skip-opt --no-create-db --complete-insert --add-drop-table $db $MYVIEWS | \
sed -r 's/DEFINER=`[^`]+`#`[^`]+`/DEFINER=CURRENT_USER/g' | mysql $LOCALCONNECTION $db
fi
done
echo "OK!"
Copy mysql database from remote server to local computer
I ran into the same problem. And I could not get it done with the other answers. So here is how I finally did it (yes, a beginner tutorial):
Step 1: Create a new database in your local phpmyadmin.
Step 2: Dump the database on the remote server into a sql file (here I used Putty/SSH):
mysqldump --host="mysql5.domain.com" --user="db231231" --password="DBPASSWORD" databasename > dbdump.sql
Step 3: Download the dbdump.sql file via FTP client (should be located in the root folder)
Step 4: Move the sql file to the folder of your localhost installation, where mysql.exe is located. I am using uniform-server, this would be at C:\uniserver\core\mysql\bin\, with XAMPP it would be C:\xampp\mysql\bin
Step 5: Execute the mysql.exe as follows:
mysql.exe -u root -pYOURPASSWORD YOURLOCALDBNAME < dbdump.sql
Step 6: Wait... depending on the file size. You can check the progress in phpmyadmin, seeing newly created tables.
Step 7: Done. Go to your local phpmyadmin to check if the database has been filled with the entire data.
Hope that helps. Good luck!
Note 1: When starting the uniformer-server you can specify a password for mysql. This is the one you have to use above for YOURPASSWORD.
Note 2: If the login does not work and you run into password problems, check your password if it contains special characters like !. If so, then you probably need to escape them \!.
Note 3: In case not all mysql data can be found in the local db after the import, it could be that there is a problem with the mysql directives of your dbdump.sql
Better yet use a oneliner:
Dump remoteDB to localDB:
mysqldump -uroot -pMypsw -h remoteHost remoteDB | mysql -u root -pMypsw localDB
Dump localDB to remoteDB:
mysqldump -uroot -pmyPsw localDB | mysql -uroot -pMypsw -h remoteHost remoteDB
C:\Users\>mysqldump -u root -p -h ip address --databases database_name -r sql_file.sql
Enter password: your_password
This answer is not remote server but local server. The logic should be the same. To copy and backup my local machine MAMP database to my local desktop machine folder, go to console then
mysqldump -h YourHostName -u YourUserNameHere -p YourDataBaseNameHere > DestinationPath/xxxwhatever.sql
In my case YourHostName was localhost. DestinationPath is the path to the download; you can drag and drop your desired destination folder and it will paste the path in.
Then password may be asked:
Enter password: xxxxxxxx

Using mysqldump and database users

I'm attempting to assemble all the options that I need for mysqldump to create everything used by my applications database into a single script. This includes the database itself and all the database users/passwords/privileges.
I've got it all figured out with the exception of the user piece... here's what I'm currently using:
mysqldump -h host -u root -p \
--add-drop-database --routines -B database_name > backup.sql
So, what am I missing?
The database users/passwords/privileges are kept in the mysql database, and won't get dumped with your dump command. You'll have to add that database as well to the list of DBs to dump:
mysqldump ... --routines --databases database_name mysql > backup.sql
or just dump everything:
mysqldump ... --routines --all-databases > backup.sql
When dumping the mysql database, don't forget:
--flush-privileges Emit a FLUSH PRIVILEGES statement after dumping the mysql
database. This option should be used any time the dump
contains the mysql database and any other database that
depends on the data in the mysql database for proper
restore.
So, I had a fundamental misunderstanding. Users are not specific to a database, but are rather created at the server level.
You can view all existing users with the following query:
SELECT * FROM mysql.user;
Knowing this, it's pretty obvious that mysqldump shouldn't do anything with users. However, if you need an answer to exporting/importing users and perms I suggest you check the following article - it helped me out.
http://pento.net/2009/03/12/backing-up-permissions-for-individual-databases/
My apologies for the noise on the board, but I figured I'd leave the post incase anyone else has the same misunderstanding.
Full process for me when migrating from one Mac OS X dev environment to a new one.
0) Get rid of newer version of MySQL on new MacBook
I had accidentally installed MySQL 8, so I had to remove it because it was newer than my old MacBook.
# Remove binaries
$ brew uninstall mysql
# Remove data/config that is leftover
$ rm -r /usr/local/var/mysql/
1) Install same version of MySQL on new MacBook
# Install version that matched old MacBook
$ brew install mysql#5.7
# Because it is an old version, you have to do a special configuration step
$ echo 'export PATH="/usr/local/opt/mysql#5.7/bin:$PATH"' >> ~/.bash_profile
$ source ~/.bash_profile
# Start server
$ mysql.server start
2) Dump data on old MacBook
$ mysqldump -uroot --flush-privileges --routines --all-databases > complete_dump.sql
3) Restore data on new MacBook
$ mysql -p -uroot < complete_dump.sql
You may want to take a look at mysqlpump, it can dump all databases, and can export the users as CREATE USER and GRANT statements instead of relying on the mysql system db + mysql_upgrade.
mysqlpump # Dumps (almost) all databases (see [2])
mysqlpump --exclude-databases=% --users # Dumps all user accounts
It's unclear from the docs if you can do mysqlpump --users and get both all databases and the users.
Some system tables get omitted by default, see restrictions.
mysqldump version 10.19 contains the option --system=users wich adds CREATE USER with the GRANT commands into the dump.
mysqldump -h host -u root -p \
--add-drop-database --routines -B database_name \
--system=users > backup.sql
source: https://mariadb.com/kb/en/mysqldump/
Connect to your database server and execute:
select concat('show grants for ','\'',user,'\'#\'',host,'\'') from mysql.user;
You'll get something like this:
+--------------------------------------------------------+
| concat('show grants for ','\'',user,'\'#\'',host,'\'') |
+--------------------------------------------------------+
| show grants for 'mariadb.sys'#'localhost' |
| show grants for 'mysql'#'localhost' |
| show grants for 'root'#'localhost' |
+--------------------------------------------------------+
Capture the output to some temporary file.
And then cycle through each line in that temporary file, sending it against your mysql server, capturing the output.
Output will be something that you can use to reconstruct users on another server:
GRANT ALL PRIVILEGES ON *.* TO `root`#`localhost` IDENTIFIED VIA mysql_native_password USING 'invalid' OR unix_socket WITH GRANT OPTION
GRANT PROXY ON ''#'%' TO 'root'#'localhost' WITH GRANT OPTION
Here's a script I'm currently using:
mysql -u${BACKUP_DB_USER} -p${BACKUP_DB_PASSWORD} -e"select concat('show grants for ','\'',user,'\'#\'',host,'\'') from mysql.user" > user_list_with_header.txt
sed '1d' user_list_with_header.txt > ./user.txt
while read user; do mysql -u${BACKUP_DB_USER} -p${BACKUP_DB_PASSWORD} -e"$user" > user_grant.txt; echo "-- ${user}" >> user_privileges.txt; sed '1d' user_grant.txt >> user_privileges.txt; done < user.txt
echo "flush privileges" >> user_privileges.txt;
awk '{print $0";"}' user_privileges.txt > all_user_privileges_final.sql
rm user.txt user_list_with_header.txt user_grant.txt user_privileges.txt
You'll have all grant statements in the file all_user_privileges_final.sql.
Of course, you can limit your initial query to list only user(s) you want.
You can only use the option --system=users to get the user's dump from mysql/MariaDB if mysql client is for MariaDB.
For example:
check mysql --version. If output is like mysql Ver 15.1 Distrib 10.6.8-MariaDB then
mysqldump -h <hostname> -u <usename> -p --system=users > mysqldb_users.sql