#!/bin/sh # # Mini SQL dump (restore) utility - minisqldump.cgi ver='0.36b' # # This script works as a CGI and also as a command line tool. # It does dump/restore entire MySQL DB using the most efficient manner. # Written in almost pure Shellscript. # # For the dump, it uses simple "Select * From `table`;" >table.dat # and it generate "Drop table... Create Table..." similar to 'mysqldump'. # # For the restore, it uses "LOAD DATA LOCAL INFILE ..." and the data file # created by the dump operation. # # Note: It can use 'mysqldump' for backup if 'mysqldump' method is chosen, # and it can restore from files created by 'mysqldump', too. # # The table creation sql file and the table data files can be gathered in # a user specified format, instead of dumping to the currect directory. # .zip, .tar, .tar.gz, .tgz, .tar.bz2, .tbz2 are supported. # # When invoked as a CGI, it shows simple form to input parameters. # This script accepts both GET and POST method. # # Installation: # # Simply, copy this file to a well protected directory as 'minisqldump.cgi' # and set permission to 700 (or 755 in non-SuExec environment). # No editing required (unless mysql commands are in non-standard path). # Juse make sure to protect it at least with password (for CGI) # # Usage: # # As a CGI: Access https://example.com/safedir/minisqldump.cgi # and enter parameters in the form. # # Or supply the parameter in the address bar or link. # https://example.com/safedir/minisqldump.cgi?u=USER&p=PASS&h=SERVER&d=DBNAME&f=FILEPATH # First five parameters can be blank if you edit the Config section # and setup default parameters (that can be overridden). # # Add &r=1 if you want to restore the database. # Use t=table1+table2+rable5 if you want to specify table to backup/restore in URL. # # You should use this script with HTTPS as much as possible. # Otherwise, you will be sending the password in a clear text ..... # # # As a Command: minisqldump.cgi [-m] [-r] USER|- PASS|- SERVER|- DBNAME|- [FILEPATH|-] [table1 [table2] ...] # Add -r option BEFORE other parameters if you want to restore the database. # Use -m option if you want to use 'mysqldump' instead of Quick(default) method. # You can use a dash in places of USER,PASS,SERVER,DBBANE,and FILEPATH # if you edit Config section and setup default parameters for them. # Optional tablenames can be specified after FILEPATH (or a dash) to list # tables you want to backup/restore. Without these, all tables will be treated. # # Perform `minisqldump.cgi -h` for more info, or read this source code. # # # In both CGI and command line, FILEPATH parameter is an option. # If you specify FILEPATH ending with one of the compression format supported, # minisqldump.cgo will create the file and delete temporary dir/files. # # Saving the backup files in the current directory in zip format. # ex. minisqldump.cgi USER PASS SERVER DBNAME minibackup.zip # # Saving the backup files in /home/USER/ in tar format. # ex. minisqldump.cgi USER PASS SERVER DBNAME ~/minibackup.tar # # Restoring from tgz file in upper dir # ex(restore). minisqldump.cgi -r USER PASS SERVER DBNAME ../minibackup.tgz # # Using 'mysqldump' instead of quick & efficient default method. # 'mysqldump' method may offer better compatibility in some case. # ex(backup). minisqldump.cgi -m USER PASS SERVER DBNAME backup.sql # ex(restore). minisqldump.cgi -m -r USER PASS SERVER DBNAME backup.sql # # # If you specify other FILEPATH, minisqldump.cgi will create it as a directory # (if it doesn't exist) and simply place all files in it, and leave it. # # Saving the backup files in a directory 'bu2005-10-15' without compression # ex. minisqldump.cgi USER PASS SERVER DBNAME bu2005-10-15 # # # WARNING: Although I've tested many times, this script is still under testing # and you should keep a backup of your DB using mysqldump, time to time. # # Advantage of this script: # # Unlike mysqldump. minisqldump does both backup and restore, and do it # without character encoding conversion in a smaller data format. # Also, it uses "LOAD DATA LOCAL INFILE..." which is more efficient. # And it compress/extract the backup automatically if specified. # It supports 5 storing/compression formats of your choice, too. # # So, minisqldump should work quicker for both backup and restoring # using less resources. # # Latest version will be available at: # http://check-these.info/MiniSqlDump.html # http://check-these.info/tools/minisqldump_cgi.txt # CHECK='http://check-these.info' DATE=`date "+%y-%m-%d"` # ###### Config section ########## # If you want to avoid entering some fields, replcase USERNAME and/or # other strings according to your own MySQL DB setting, # and remove # to activate. # Note: DO NOT put SPACES around equal sign =, please. # If you set PASSWORD here, make sure to set permission of 700. # # U='USERNAME' # P='PASSWORD' # H='MYSQLSERVER' # D='DBNAME' # The backup will be gathered & commpressed in the file in current directory # if you don't specify 5th commandline option or File/path form field. # You can use .zip .tar. .tar.zg (.tgz) .tar.bz2 (.tbz2) or other name, # whick will be used for the directory of none compressed data files. # F='backup.tgz' # MySQL commands path and file name. Usually, you don't have to change these. # MYPATH="/usr/local/bin" MYSQL="${MYPATH}mysql" MYDUMP="${MYPATH}mysqldump" ps='ps uxww' up='uptime' # ###### END config ######### waitbg () { CC=''; CCC='0' while :;do CC="${CC}x"; CCC=$(( $CCC + 1 )) case `jobs` in '') break;; esac sleep 3; echo -n '.' case "$CC" in "xxxxxxxxxx") CC=''; echo;;esac case "$CCC" in "$Max") echo "$Mess"; kill $!;Killed='1'; return;; esac done } ######## dump function ########## dumpdb () { echo -e "u='$u', p='********', h='$h', d='$d', f='$f', t='$t', r='$r' m='$m', res='$res'" ### Use mysqldump if -m optiont or m=1 is detected ### case "$m" in 1) if [ -z "$f" ];then f="backup.sql";fi echo "Dumpimg with 'mysqldump' (backupfile='$f') ..." case "$t" in '+') t='';;esac ff="$f" case "$f" in *.tar.gz|*.tar.bz2|*.zip|*.tar|*.gz|*.tgz|*.bz2|*.tbz2) ff="${f%.*}" case "$ff" in *.tar) ff="${ff%.*}";; esac $MYDUMP -u$u -p$p -h$h $d $t >$ff & Max='300'; Mess="mysqldump running too long. Terminating." waitbg; case "$Killed" in '1') return;;esac echo "Done";echo "Compressing ..." case "$f" in *.zip) zip "$ff" "$ff" &;; *.tar.gz|*.tgz) tar czvf "$f" "$ff" &;; *.tar.bz2|*.tbz2) tar cjvf "$f" "$ff" &;; *.gz) gzip -f "$ff" &;; *.bz2) bzip2 -f "$ff" &;; esac Max='300'; Mess="Compression process running too long. Terminating." waitbg; case "$Killed" in '1') return;;esac case "$f" in *.zip|*.tar.gz|*.tgz|*.tar.bz2|*.tbz2) rm $ff ;;esac ;; *) $MYDUMP -u$u -p$p -h$h $d $t >$f;; esac echo "Done.";ls -al "$f"; return;; esac ### Quick method ### case "$f" in # Create (temporary) directory for storing dump data '') ;; *.tar.gz|*.tar.bz2) dbdir="${f%.*.*}"; if [ -f "$dbdir" ];then rm "$dbdir";fi; mkdir "$dbdir";cd "$dbdir";; *.zip|*.tar|*.gz|*.tgz|*.bz2|*.tbz2) dbdir="${f%.*}"; if [ -f "$dbdir" ];then rm "$dbdir";fi; mkdir "$dbdir";cd "$dbdir";; *) if [ ! -d "$f" ];then if [ -f "$f" ];then rm "$f";fi;mkdir "$f";fi;cd "$f";; esac if [ "$?" != "0" ];then echo "Error: unknown reason ...";return;fi M="$MYSQL --quick -s -u$u -p$p -h$h -D$d -e" # Get the list of tables TL=`$M "SHOW TABLES"` C='' # Construct 'Show Create Table' command and dump each table data for tn in $TL do case "$t" in *" $tn "*|"+") # If the table matches the list case "$t" in "+") ;; *) t="${t%[\ ]$tn[\ ]*}${t##*[\ ]$tn}" ;;esac C=$C"SHOW CREATE TABLE $tn;" $M "SELECT * FROM $tn;" >$tn.dat echo "Table '$tn' saved." ;; esac done case "$t" in *[!\ +]*) echo "Error: Specified table(s) $t not found in the database.";; esac $M "$C" |cut -f 2 |sed 's/\\n//g' >$d.tables.sql # Save table creating SQL # Compress if specified and delete temporary directory if [ -n "$f" ];then cd .. ;fi if [ -n "$dbdir" ];then case $f in *.zip) zip -r "$dbdir" "$dbdir";; *.tar) tar cvf "$f" "$dbdir";; *.gz|*.tgz) tar czvf "$f" "$dbdir";; *.bz2|*.tbz2) tar cjvf "$f" "$dbdir";; esac rm -rf "$dbdir" fi if [ -n "$f" ];then ls -al "$f";fi # Show the detail of resulted file(s) } ######## restore function ########## restoredb () { echo -e "u='$u', p='********', h='$h', d='$d', f='$f', t='$t', r='$r' m='$m', res='$res'" ### Use simple mysql INSERT if -m option or m=1 is detected ### case "$m" in 1) if [ -z "$f" ];then f="backup.sql";fi case "$t" in '+') t='';;esac case "$f" in *.zip) ff=`unzip -o "$f"`;echo "***$ff***";ff="${ff#${ff%:*}}" ff="${ff%${ff##*[!\ ]}}";ff="${ff#:[\ ]}";echo "***$ff***";; *.tar) ff=`tar xvf "$f"`;; *.tar.gz|*.tgz) ff=`tar xzvf "$f"`;; *.gz) ff=`gunzip -l "$f"`; ff=${ff##*\ };gunzip -c $f >$ff ;; *.tar.bz2|*.tbz2) ff=`tar xjvf "$f"`;; *.bz2) ff=`bunzip2 -l "$f"`;ff=${ff##*\ };bunzip2 -c $f >$ff ;; esac #echo "DBG ff=$ff"; # case "$res" in 1) echo -n "Using 'restore.cgi' (backupfile='$f') ..." # ./restore.cgi "$f" "$u" "$p" "$h" "$d";echo "Done.";return;; # esac case $t in *[!\ ]*) echo "All tables in given sql file will be restored eventhough you specified these tables:$t";; esac case "$f" in *.tar.gz|*.tar.bz2|*.zip|*.gz|*.tgz|*.bz2|*.tbz2) echo "Restoring with 'mysql' (backupfile='$ff', decompressed from '$f' ) ..." $MYSQL -u$u -p$p -h$h $d <$ff && rm "$ff";; *) echo "Restoring with 'mysql' (backupfile='$f') ..."; $MYSQL -u$u -p$p -h$h $d <$f;; esac echo "Done." $MYSQL -v -v -v -u$u -p$p -h$h $d -e "Show Table Status;"; return;; esac ### Quick method ### # Check if the file (directory) exists when its specified error () { echo "Error: '$f' not found";return 1; } case "$f" in *.tar.gz|*.tar.bz2) dbdir="${f%.*.*}";; *.zip|*.tar|*.gz|*.tgz|*.bz2|*.tbz2) dbdir="${f%.*}";; esac # Extract files if compressed format is specified case "$f" in '') ;; *.zip) if [ ! -f "$f" ];then error;return;fi;unzip "$f" && cd "$dbdir";; *.tar) if [ ! -f "$f" ];then error;return;fi;tar xvf "$f" && cd "$dbdir";; *.gz|*.tgz) if [ ! -f "$f" ];then error;return;fi;tar xzvf "$f" && cd "$dbdir";; *.bz2|*.tbz2) if [ ! -f "$f" ];then error;return;fi;tar xjvf "$f" && cd "$dbdir";; *) if [ ! -d "$f" ]; then error;return;fi;cd "$f";; esac if [ "$?" != "0" ]; then echo "Error: possibly wrong fromat '$f'"; exit;fi # Drop, Create, and Load Data for each table M="$MYSQL -v -v -v -u$u -p$p -h$h -D$d -e" dd="$d.tables.sql" if [ ! -r $dd ];then for dd in *.tables.sql ;do break;done;fi echo "Restoring using $dd" while read -r ct do tn=${ct#*TABLE ?} ; tn=${tn%%? *} case "$t" in *" $tn "*|"+") case "$t" in "+") ;; *) t="${t%[\ ]$tn[\ ]*}${t##*[\ ]$tn}" ;;esac $M "DROP TABLE IF EXISTS $tn;$ct; LOAD DATA LOCAL INFILE '$tn.dat' INTO TABLE $tn" 2>&1 ;; esac done <$dd case "$t" in *[!\ +]*) echo "Error: Specified table(s) $t not found in the backup.";; esac # Remove temporary directory if it's there if [ -n "$dbdir" ]; then cd .. && rm -rf "$dbdir";fi } ####### helper function(s) ####### updatenow () { # Install/update function exec 2>&1 case "$UF" in *_[pc][hg][pi].txt) RF="${UF%_*}.${UF##*_}" RF="${RF%.txt}";; *)RF="$UF";;esac if [ -f "$RF" ];then if [ ! -w "$RF" ];then echo "Error: The file: $RF isn't writalbe. Please change the permission to 700 (or 755)"; if [ -n "$AS_CGI" ];then return;else exit;fi fi cp -vf "$RF" "$RF.$DATE" fi echo "Downloading current version ...." wget -t 1 -nd "http://serv.check-these.info/tools/$UF" && sleep 2 && chmod 700 "$UF" && mv -vf "$UF" "$RF" && echo "Update done" || echo "Update failed. Please retry later if it was downloading problem. If the problem persists, contact author: minisqldump (atmark) check-these.info "; case "$RF" in *.cgi) export SCRIPT_FILENAME=""; ./$RF -V ;;esac if [ -n "$AS_CGI" ];then echo '
"
AS_CGI=1
exec 2>&1
# Get query data from QUERY_STRING (GET method) or stdin (POST method)
case "$REQUEST_METHOD" in
[gG][eE][tT]) qs="$QUERY_STRING";;
# *) while : ;do read -r post || break; qs="$qs$post";done ;;
# Read only one line
*) read -r qs;;
esac
qsl="${#qs}"
while : ;do # Primitive form parsing. No special chars treated
C=$(($C + 1)); pair="${qs%%[&]*}"; qsp="$qs";qs="${qs#*[&]}"
id="${pair%%=*}"; v="${pair#*=}"
#echo -e "DBG $C:\nqss=$qss\nqs=$qs\npair=$pair\nid=$id\nv=$v"
case "$id" in '');; *[!0-9a-zA-Z_-.]*) echo "Error:
You can't use special characters in parameter name '$id'";exit 3;;
"$pair") eval "$id=''";; *) eval "$id='$v'";;
esac
case "$qs" in ''|\&|"$qsp") break;;esac
case "$C" in '50') echo "Error: Max loop reached $C";exit 2;;esac
done
case "$c" in "w") UF="$fn"; updatenow;qsl=0;;esac
case "$m" in 1) m1="$m0";m0='';; esac
case "$res" in 1) res0="$r0";; esac
case "$r" in 1) cmd="$restore";r1=$r0;r0='' 2>&1;; esac
# Replace %20 and + in $t with a space.
while :;do case $t in *%20*)t="${t%%[%]20*} ${t#*[%]20}";; *)break;;esac;done
while : ;do case $t in *+*) t="${t%%+*} ${t#*+}";; *)break;; esac;done
host=`hostname`
case "$host" in *powweb*) pow=1;; *) ps='' ;;esac
else # Invoked as a command
pssave="$ps";ps=''
case "$#" in '0') usage;exit;;esac
while :; do case "$1" in #Check and consume options
'-m') shift; m1=$m0;m0='';m=1;;
'-res') shift; res0="$r0";res=1;;
'-r') cmd="$restore"; shift; r1=$r0;r0='';r=1;;
'-ps') shift;ps="$pssave";; # run ps. ps may reaveal the password
'-nops') shift;ps='';; # Don't run ps. (Default in the command line mode)
'-noup') shift;up='';; # Don't run uptime.
'-V'|'--version') shift; echo $version;exit;;
'-h'|'--help') shift;usage;exit;;
'-x'|'--extensive') shift;usage;echo;grep '^#\( \|$\)' $0;exit;;
'-w'|'--update') updatenow;exit;; # Get the new version. Auto update.
'-'?*) echo -e "Error: unknown option:$1\n";usage;exit;;
*) break;;
esac;done
qsl="$#"
if [ "$qsl" -gt "3" ];then
u="$1";p="$2";h="$3";d="$4";f="$5";shift 4
if [ -n "$1" -a -n "$2" ];then shift;
while : ;do case $1 in '') break;; *) t="$t $1"; shift;; esac;done
case "$t" in " "*) t=${t#?};;esac
fi
fi
fi
# Check parameters, use the default if it's defined
usave="$u"; psave="$p"; hsave="$h"; dsave="$d"
case "$u" in ''|'-') u="$U" ;; esac
case "$p" in ''|'-') p="$P" ;; esac
case "$h" in ''|'-') h="$H" ;; esac
case "$d" in ''|'-') d="$D" ;; esac
case "$f" in ''|'-') f="$F" ;; esac
if [ "$qsl" != "0" ];then
if [ -z "$u" -o -z "$p" -o -z "$h" -o -z "$d" ];then
echo -e "Error: missing parameter(s)
u='$u', p='********', h='$h', d='$d', f='$f', t='$t', r='$r'"
else
tsave="$t"; case "$t" in '') t='+';; *) t=" $t ";;esac
hostname;$up; $cmd; $up; $ps; # Execut the command
fi
fi
# Input form (if invoked as a CGI). Modify as you wish.
if [ -n "$AS_CGI" ];then
if [ "$qsl" != "0" ];then echo "
";fi
echo "
#1 Quick(default) method is similar to '--tab=path, -T path' option of mysqldump, but it isn't restricted to the same server.PowWeb's OPS has MySQL backup and import utility. OPS->Packages->MySQL It is very easy and convenient if you want to download ready-made compressed backup and upload & restore from the data you have in your machine. * Currently, you need to decompress the file (on your machine) to use the import feature. The backup created by 'mysqldump' method of this script is compatible with PowWeb's utility. This script can restore the daily backup generated by PowWeb once you upload it (via FTP or upload script) to somewhere in your site, too. (It'll decompress the backup for you, automatically, if the file has proper extension.) For taking the backup instantly, this tool is more convenient and restore operation is much quicker with default 'Quick' method, but you need to download to your machine to have the backup really secure. Please report BUG or problem to PowWeb forum & PM me if you don't get reply." else echo "