Catching exit code after executing mysql query - mysql

I'm working on a bash script that will query mysql. I would like to add some error checking. Let say if the following query for some reason fails I want to catch the exit error and exit the script. For example this is part of my script.
QUERY="SELECT DISTINCT `TABLE_SCHEMA`, `TABLE_NAME`
FROM `information_schema`.`TABLES`
WHERE table_schema NOT IN ( 'mysql', 'information_schema', 'performance_schema' )"
mysql -u user -pPASSWD --batch -N -e "$QUERY" | while read DATABASE TABLE;
do
...
...
...
done
How could i catch the exit code after the scripts run the "$QUERY". I was thinking something like this. But it doesn't seem to work.
mysql -u user -pPASSWD --batch -N -e "$QUERY" echo $? | while read DATABASE TABLE;
Any ideas

You are in the good way: $? is the flag to check:
$ mysql -h mydb <<< "SELECT * FROM MyDB.some_table_that_exists;"
$ echo $?
0
$ mysql -h mydb <<< "SELECT * FROM MyDB.asdfasdfasdf;"
ERROR 1146 (42S02) at line 1: Table 'MyDB.asdfasdfasdf;' doesn't exist
$ echo $?
1
So what you can do is to execute the query and then:
if [ $? ... ]; then ...

Related

How to take all database backup same as db name

I am using MySQL on centos7. I have 50 databases Like database1, database2...., database50.
How can I set a cronjob for take a dump every day of all database same as database name [ Like database1.sql, database2.sql .... database50.sql ] using single command or script.
Please provide some adequate solution that will be appreciated.
Thanks.
Convert the current date to an integer number of days since some starting date.
Take that modulo 50. This gives you 0 .. 49.
Add 1 and concatenate. Now you have database1 .. database50. Put that in the shell variable db
mysqldump ... $db >$db.sql
I am using this script
#! /bin/bash
# MySQL database backup (databases in separate files) with daily, weekly and monthly rotation
# Sebastian Flippence (http://seb.flippence.net) originally based on code from: Ameir Abdeldayem (http://www.ameir.net)
# You are free to modify and distribute this code,
# so long as you keep the authors name and URL in it.
# Modified by IVO GELOV
# How many backups do you want to keep?
MAX_DAYS=5
# Date format that is appended to filename
DATE=`date +'%Y-%m-%d'`
DATSTR=`date '+%Y%m%d' -d "-$MAX_DAYS days"`
# MySQL server's name
SERVER=""
# Directory to backup to
BACKDIR="/var/db_arhiv/mysql"
#----------------------MySQL Settings--------------------#
# MySQL server's hostname or IP address
HOST="localhost"
# MySQL username
USER="user"
# MySQL password
PASS="password"
# List all of the MySQL databases that you want to backup,
# each separated by a space. Or set the option below to backup all database
DBS="db1 db2"
# Set to 'y' if you want to backup all your databases. This will override
# the database selection above.
DUMPALL="y"
# Custom path to system commands (enable these if you want use a different
# location for PHP and MySQL or if you are having problems running this script)
MYSQL="/usr/local/mysql/bin/mysql"
MYSQLDUMP="/usr/local/mysql/bin/mysqldump"
function checkMysqlUp() {
$MYSQL -N -h $HOST --user=$USER --password=$PASS -e status > /dev/null
}
trap checkMysqlUp 0
function error() {
local PARENT_LINENO="$1"
local MESSAGE="$2"
local CODE="${3:-1}"
if [[ -n "$MESSAGE" ]] ; then
echo "Error on or near line ${PARENT_LINENO}: ${MESSAGE}; exiting with status ${CODE}"
else
echo "Error on or near line ${PARENT_LINENO}; exiting with status ${CODE}"
fi
exit "${CODE}"
}
trap 'error ${LINENO}' ERR
# Check backup directory exists
# if not, create it
if [ ! -e "$BACKDIR/$DATE" ]; then
mkdir -p "$BACKDIR/$DATE"
echo "Created backup directory (${BACKDIR}/${DATE})"
fi
if [ $DUMPALL = "y" ]; then
echo "Creating list of databases on: ${HOST}..."
$MYSQL -N -h $HOST --user=$USER --password=$PASS -e "show databases;" > ${BACKDIR}/dbs_on_${SERVER}.txt
# redefine list of databases to be backed up
DBS=`sed -e ':a;N;$!ba;s/\n/ /g' -e 's/Database //g' ${BACKDIR}/dbs_on_${SERVER}.txt`
fi
echo "Backing up MySQL databases..."
#cd ${LATEST}
for database in $DBS; do
if [ ${database} = "information_schema" ] || [ ${database} = "performance_schema" ] || [ ${database} = "pinba" ]
then
continue
fi
echo "${database}..."
$MYSQLDUMP --host=$HOST --user=$USER --password=$PASS --default-character-set=utf8 --routines --triggers --lock-tables --disable-keys --force --single-transaction --allow-keywords --dump-date $database > ${BACKDIR}/${DATE}/${SERVER}$database.sql
done
if [ $DUMPALL = "y" ]; then
rm -f ${BACKDIR}/dbs_on_${SERVER}.txt
fi
# dump privileges
$MYSQL -N -h $HOST --user=$USER --password=$PASS --skip-column-names -A -e "SELECT CONCAT('SHOW GRANTS FOR ''',user,'''#''',host,''';') FROM mysql.user" | $MYSQL -N -h $HOST --user=$USER --password=$PASS --skip-column-names -A > ${BACKDIR}/${DATE}/${SERVER}_grants.sql
# delete older files
for x in `find ${BACKDIR}/20* -type d`
do
xd=`basename "${x//-/}"`
if [[ $xd < $DATSTR ]]
then
rm -rf "$x"
fi
done
echo "MySQL backup is complete"

How to run a MySQL procedure from a Linux shell script and store its output in a file

I have a mysql procedure which I want to run from a shell script in linux and store the output in a log file. But my script is not working. Below is my script:
#!/bin/bash
source CX20-PIM-properties.prop
status=$(mysql -u $user -h $host -D $database -se "call fetchFromPAsIsToPIDX()")
if [ $status ]; then
echo "Procedure executed successfully" | tee procedure_output.log
else
echo "Procedure execution failed" | tee procedure_output.log
fi
And the output is below:
[anurag#pimdev0 ~]$ ./load-from-AsIs-to-IDX.sh
Procedure execution failed
You should store the return value of cmd in status not stdout of cmd.
#!/bin/bash
source CX20-PIM-properties.prop
if [ `mysql -u $user -h $host -D $database -se "call fetchFromPAsIsToPIDX()" &> /dev/null` ]; then
echo "Procedure executed successfully" | tee procedure_output.log
else
echo "Procedure execution failed" | tee procedure_output.log
fi

How to check mysql queries was successful in shell script

I need to set traction for all mysql queries in shell script, so I have to find all queries are successfullt executed or not, so my simple code is below. here I have to find all mysql queries are done successfully or not.
#!/bin/bash
set -x
date=$(date +"%Y")
month=$(date +"%m")
day=$(date +"%d")
user="appuser"
password="Appuser"
mysql=/usr/local/mysql/bin/mysql
db="finance"
tbname="cash_expense"
$mysql -u$user -p$password -S"/var/lib/mysql/mysql.sock" $db -N -e"create table new like $tbname;rename table $tbname to $tbname$date;rename table new to $tbname;truncate table $tbname;"
you can check the exit code of mysql
demo:
~$ cat a.sh
#!/bin/sh
mysql -e"select 1"
ret=$?
echo "correct syntax: $ret"
mysql -e"select bad syntax"
ret=$?
echo "bad syntax: $ret"
if [ "$ret" = "0" ]; then
echo "mysql executed ok"
else
echo "mysql executed failed"
fi
~$ sh a.sh
+---+
| 1 |
+---+
| 1 |
+---+
correct syntax: 0
ERROR 1054 (42S22) at line 1: Unknown column 'bad' in 'field list'
bad syntax 1
mysql executed failed

How to run MySQL command on bash?

The following code works on the command line
mysql --user='myusername' --password='mypassword' --database='mydatabase' --execute='DROP DATABASE myusername;
CREATE DATABASE mydatabase;'
However, it doesn't work on bash file on execution
#!/bin/bash
user=myusername
password=mypassword
database=mydatabase
mysql --user='$user' --password='$password' --database='$database' --execute='DROP DATABASE $user; CREATE DATABASE $database;'
I receive the following error:
ERROR 1045 (28000): Access denied for user '$user'#'localhost' (using password: YES)
How to make the bash file run as the command line?
Use double quotes while using BASH variables.
mysql --user="$user" --password="$password" --database="$database" --execute="DROP DATABASE $user; CREATE DATABASE $database;"
BASH doesn't expand variables in single quotes.
This one worked, double quotes when $user and $password are outside single quotes. Single quotes when inside a single quote statement.
mysql --user="$user" --password="$password" --database="$user" --execute='DROP DATABASE '$user'; CREATE DATABASE '$user';'
I have written a shell script which will read data from properties file and then run mysql script on shell script. sharing this may help to others.
#!/bin/bash
PROPERTY_FILE=filename.properties
function getProperty {
PROP_KEY=$1
PROP_VALUE=`cat $PROPERTY_FILE | grep "$PROP_KEY" | cut -d'=' -f2`
echo $PROP_VALUE
}
echo "# Reading property from $PROPERTY_FILE"
DB_USER=$(getProperty "db.username")
DB_PASS=$(getProperty "db.password")
ROOT_LOC=$(getProperty "root.location")
echo $DB_USER
echo $DB_PASS
echo $ROOT_LOC
echo "Writing on DB ... "
mysql -u$DB_USER -p$DB_PASS dbname<<EOFMYSQL
update tablename set tablename.value_ = "$ROOT_LOC" where tablename.name_="Root directory location";
EOFMYSQL
echo "Writing root location($ROOT_LOC) is done ... "
counter=`mysql -u${DB_USER} -p${DB_PASS} dbname -e "select count(*) from tablename where tablename.name_='Root directory location' and tablename.value_ = '$ROOT_LOC';" | grep -v "count"`;
if [ "$counter" = "1" ]
then
echo "ROOT location updated"
fi

How can I drop all the views from a MYSQL Database?

My database had lots of views and it was impossible to drop them one by one.
I would like to just drop them all because the database doesn't refresh structure changes of the tables in the view that select from them.
If you want to do this in the MySQL client, you can dynamically generate the DDL statements using information_schema, dump them to a SQL script, and then execute that script.
Example:
select concat('drop view ',table_schema,'.',table_name,';') as ddl
into outfile '/tmp/drop_all_views.sql'
from information_schema.views
where table_schema = 'your_schema';
\. /tmp/drop_all_views.sql
After searching on the web, I found a shell script to drop all tables here: http://www.cyberciti.biz/faq/how-do-i-empty-mysql-database/
Then, I changed that script to drop all views of the database.
This is the final result:
#!/bin/bash
PREFIX=""
SUFFIX=""
HOST="localhost"
PORT="3306"
while getopts p:s:h:P: OPCAO; do
case "${OPCAO}" in
p) PREFIX="${OPTARG}" ;;
s) SUFFIX="${OPTARG}" ;;
h) HOST="${OPTARG}" ;;
P) PORT="${OPTARG}" ;;
esac
done
shift $((OPTIND-1))
MUSER="$1"
MPASS="$2"
MDB="$3"
# Detect paths
MYSQL=$(which mysql)
AWK=$(which awk)
GREP=$(which grep)
if [ $# -eq 0 ]
then
echo "Usage: $0 [-h Host] [-P Port] [-p Prefix-View-Name] [-s Suffix-View-Name] {MySQL-User-Name} {MySQL-User-Password} {MySQL-Database-Name}"
echo "Drops all views from a MySQL"
exit 1
fi
TABLES=$($MYSQL -h $HOST -P $PORT -u $MUSER -p$MPASS $MDB -e "SELECT table_name FROM information_schema.views WHERE table_schema = '$MDB' AND table_name LIKE '$PREFIX%$SUFFIX';" | $AWK '{ print $1}')
for t in $TABLES
do
echo "Deleting $t view from $MDB database..."
$MYSQL -h $HOST -P $PORT -u $MUSER -p$MPASS $MDB -e "drop view $t"
done
This solution will work just for who uses Unix-like systems.
To call the script, I used:
./script.sh [-h host] [-P port] [-p prefixViewName] [-s suffixViewName] username password databaseName
EDIT: I improved the script to accept option parameters, like the host, port and also a prefix and a suffix to filter what views will be dropped.