Skip to content

Instantly share code, notes, and snippets.

@andrew-azarov
Created February 13, 2016 15:32
Show Gist options
  • Save andrew-azarov/a903fc4f2f63239ee39e to your computer and use it in GitHub Desktop.
Save andrew-azarov/a903fc4f2f63239ee39e to your computer and use it in GitHub Desktop.
Simple smart backup script focused on files, mysql, pgsql and ftp upload (files are from FreeBSD edition, can be redefined in the beginning)
#!/bin/sh
# Global settings
gz_b="/usr/bin/pigz" # Gzip
awk_b="/usr/bin/awk" # Awk
echo_b="/bin/echo" # Echo
tar_b="/usr/bin/tar" # Tar
xargs_b="/usr/bin/xargs" # Xargs
cat_b="/bin/cat" # Cat
find_b="/usr/bin/find" # Find
grep_b="/usr/bin/grep" # Grep
cut_b="/usr/bin/cut" # Cut
sed_b="/usr/bin/sed" # Sed
rm_b="/bin/rm" # Rm
mkdir_b="/bin/mkdir" # Mkdir
mktemp_b="/usr/bin/mktemp" # Mktemp
basename_b="/usr/bin/basename" # Basename
date_b="/bin/date" # Date
cc_b="/usr/bin/cc" # CC, needed for pgsql backup with password
strip_b="/usr/bin/strip" # strip, the same for pgsql backup with password
tr_b="/usr/bin/tr" # Tr
ftp_b="/usr/bin/ftp" # FTP
my_dir=`pwd`
# FTP Upload settings
upload_do="NO"
upload_login=""
upload_password=""
upload_host=""
upload_p="${ftp_b} -Viu "
upload_pm="${upload_p} ftp://${upload_login}:${upload_password}@${upload_host}:21/mysql/" # Mysql dir
upload_pf="${upload_p} ftp://${upload_login}:${upload_password}@${upload_host}:21/files/" # File dir
upload_pb="${upload_p} ftp://${upload_login}:${upload_password}@${upload_host}:21/mysql/" # Binlog mysql dir
upload_pp="${upload_p} ftp://${upload_login}:${upload_password}@${upload_host}:21/pgsql/" # Pgsql dir
upload_mysql="YES"
upload_pgsql="NO"
upload_files="YES"
# File Setting
file_do="YES" # Do backup?
file_backup_d="/backup/" # Where to backup?
file_purge_time="72h" # Time backups reside
file_dir_to_b=`ls / | grep -v backup | sed -e 's/^/\//g'` # List of files and directories to backup
# Mysql Setting
mysql_do="NO" # Do backup?
mysql_u="" # Username
mysql_p="" # Password
mysql_purge_time="72h" # Time backups reside
mysql_backup_bin_logs=0 # Do we backup the binary logs?
mysql_bin_d="/usr/local/bin" # Binary directory of mysql
mysql_bin_log_d="/var/db/mysql" # Binary log directory
mysql_backup_d="/home/backup/mysql" # Where to backup?
mysql_b="${mysql_bin_d}/mysql -u${mysql_u} -p${mysql_p}" # Mysql main usage command
mysql_dump_b="${mysql_bin_d}/mysqldump -u${mysql_u} -p${mysql_p} -f" # Mysql dump usage
mysql_admin_b="${mysql_bin_d}/mysqladmin -u${mysql_u} -p${mysql_p}" # Mysql admin usage
# Pgsql Setting
pgsql_do="NO" # Do backup?
pgsql_u="" # Username
pgsql_p=""
pgsql_purge_time="72h" # Time backups reside
pgsql_bin_d="/usr/local/bin" # Binary directory of mysql
pgsql_backup_d="/home/backup/pgsql" # Where to backup?
pgsql_b="${pgsql_bin_d}/psql -U ${pgsql_u}" # Pgsql main usage command
pgsql_dump_b="${pgsql_bin_d}/pg_dump -U ${pgsql_u}" # Pgsql dump usage
pgsql_vac_b="${pgsql_bin_d}/vacuumdb -z -U ${pgsql_u}" # Pgsql vacuum usages
${echo_b} Starting backup \( `${date_b}` \)
file_backup()
{
${echo_b} File backup started \( `${date_b}` \)
if [ ! -d "${file_backup_d}" ]
then
${echo_b} "Making backup dir ${file_backup_d}"
${mkdir_b} ${file_backup_d}
fi
${echo_b} "Preparing files and directories for backup"
for dbs in ${file_dir_to_b}
do
${echo_b} -n "Compressing ${dbs}."
dbs2=`${echo_b} ${dbs} | ${tr_b} / - `
${echo_b} -n "."
nname=`${date_b} "+%Y-%m-%d-%H-%M"`
${tar_b} czf ${file_backup_d}/${nname}${dbs2}.tar.gz ${dbs} 1>/dev/null 2>&1
if [ "${upload_do}" = "YES" ]
then
${echo_b} -n ". Uploading file..."
cd ${file_backup_d}
${upload_pf} ${nname}${dbs2}.tar.gz
cd ${my_dir}
else
${echo_b} -n "."
fi
${echo_b} " Done!"
done
${echo_b} -n "Purging old backups..."
${find_b} ${file_backup_d} -type f -ctime +${file_purge_time} -depth 1 -delete
${echo_b} " Done!"
${echo_b} File backup complete \( `${date_b}` \)
}
pgsql_backup()
{
${echo_b} Pgsql Database backup started \( `${date_b}` \)
if [ ! -d "${pgsql_backup_d}" ]
then
${echo_b} "Making backup dir ${pgsql_backup_d}"
${mkdir_b} ${pgsql_backup_d}
fi
${echo_b} "Preparing databases for backup"
for dbs in `${echo_b} "${pgsql_p}" | ${pgsql_b} -l | ${sed_b} -n '4,/\eof/p' | ${grep_b} -v rows\) | ${cut_b} -f 1 -d '|' -s | ${awk_b} '{print $1}'`
do
${echo_b} -n "Vacuuming db ${dbs}..."
${echo_b} "${pgsql_p}" | ${pgsql_vac_b} -z ${dbs} > /dev/null 2>&1
${echo_b} " Done!"
${echo_b} -n "Backing up db ${dbs}.."
nname=`${date_b} "+%Y-%m-%d-%H-%M"`
${echo_b} "${pgsql_p}" | ${pgsql_dump_b} ${dbs} | ${gz_b} > ${pgsql_backup_d}/${nname}-${dbs}.sql.gz
if [ "${upload_do}" = "YES" ]
then
${echo_b} -n ". Uploading file..."
cd ${pgsql_backup_d}
${upload_pp} ${nname}-${dbs}.sql.gz
cd ${my_dir}
else
${echo_b} -n "."
fi
${echo_b} " Done!"
done
${echo_b} -n "Purging old backups..."
${find_b} ${pgsql_backup_d} -type f -ctime +${pgsql_purge_time} -depth 1 -delete
${echo_b} " Done!"
${echo_b} Pgsql Database backup complete \( `${date_b}` \)
}
mysql_backup()
{
${echo_b} Mysql Database backup started \( `${date_b}` \)
if [ ! -d "${mysql_backup_d}" ]
then
${echo_b} "Making backup dir ${mysql_backup_d}"
${mkdir_b} ${mysql_backup_d}
fi
${echo_b} "Preparing to backup non-InnoDB tables"
for dbs in `${mysql_b} -r --batch -N -e "show databases;"`
do
if [ "${dbs}" != 'information_schema' ]
then
innodbs=`${mysql_b} -r --batch -N ${dbs} -e "show table status;" | ${awk_b} -v dbs="${dbs}" '{ if ($2 == "InnoDB") {print "--ignore-table="dbs"."$1}}' | ${xargs_b} ${echo_b}`
${echo_b} -n "Backing up db ${dbs}.."
nname=`${date_b} "+%Y-%m-%d-%H-%M"`
${mysql_dump_b} --hex-blob ${innodbs} ${dbs} | ${gz_b} > ${mysql_backup_d}/${nname}-${dbs}-non-innodb-tables.sql.gz
if [ "${upload_do}" = "YES" ]
then
${echo_b} -n ". Uploading file..."
cd ${mysql_backup_d}
${upload_pm} ${nname}-${dbs}-non-innodb-tables.sql.gz
cd ${my_dir}
else
${echo_b} -n "."
fi
${echo_b} " Done!"
fi
done
${echo_b} "Preparing to backup InnoDB tables"
for dbs in `${mysql_b} -r --batch -N -e "show databases;"`
do
for innodbs in `${mysql_b} -r --batch -N ${dbs} -e "show table status;" | ${awk_b} '{ if ($2 == "InnoDB") {print $1}}'`
do
${echo_b} -n "Backing up db ${dbs}, table: ${innodbs}.."
nname=`${date_b} "+%Y-%m-%d-%H-%M"`
${mysql_dump_b} -q --single-transaction --hex-blob ${dbs} ${innodbs} | ${gz_b} > ${mysql_backup_d}/${nname}-${dbs}.${innodbs}-innodb-table.sql.gz
if [ "${upload_do}" = "YES" ]
then
${echo_b} -n ". Uploading file..."
cd ${mysql_backup_d}
${upload_pm} ${nname}-${dbs}.${innodbs}-innodb-table.sql.gz
cd ${my_dir}
else
${echo_b} -n "."
fi
${echo_b} " Done!"
done
done
if [ `${mysql_b} -r --batch -N -e 'show binary logs;' 2>&1 | ${grep_b} -c "ERROR 1381"` -ne 1 -a ${mysql_backup_bin_logs} -eq 1 ]
then
${echo_b} "Preparing binary log backup"
${mysql_admin_b} flush-logs
s=`${mysql_b} -r --batch -N mysql -e "show binary logs;" | ${awk_b} '$2>0 {i++};END{print i}'`
d=`${mysql_b} -r --batch -N mysql -e "show binary logs;" | ${awk_b} '$2>0 {print $1}' | tail -1`
r=0
for k in `${mysql_b} -r --batch -N mysql -e "show binary logs;" | ${awk_b} '$2>0 {print $1}`
do
if [ "${k}" != "${d}" -a "${r}" -le "${s}" -a ${s} -gt 0 ]
then
${echo_b} -n "Backing up binary log ${k}.."
nname=`${date_b} "+%Y-%m-%d-%H-%M"`
${cat_b} ${mysql_bin_log_d}/${k} | ${gz_b} > ${mysql_backup_d}/${nname}_binlog_${k}.gz
${rm_b} -f ${mysql_bin_log_d}/${k}
r=`expr ${r} + 1`
if [ "${upload_do}" = "YES" ]
then
${echo_b} -n ". Uploading file..."
cd ${mysql_bin_log_d}
${upload_pmb} ${nname}_binlog_${k}.gz
cd ${my_dir}
else
${echo_b} -n "."
fi
${echo_b} " Done!"
fi
done
fi
${echo_b} -n "Purging old backups..."
${find_b} ${mysql_backup_d} -type f -ctime +${mysql_purge_time} -depth 1 -delete
${echo_b} " Done!"
${echo_b} Mysql Database backup complete \( `${date_b}` \)
}
notty()
{
if [ $1 -eq 1 ]
then
temp=`${basename_b} $0`
TMPFILE=`${mktemp_b} ${temp}.XXXXX.c` || exit 1
${cat_b} <<ENDFILE>> ${TMPFILE}
/*
* Copyright (c) 2008 The DragonFly Project. All rights reserved.
*
* This code is derived from software contributed to The DragonFly Project
* by Matthew Dillon <dillon@backplane.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary fo${rm_b} must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of The DragonFly Project nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific, prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $DragonFly: src/bin/notty/notty.c,v 1.2 2008/06/24 21:13:26 thomas Exp $
*/
/*
* NOTTY.C - program to disconnect a program from the tty and close
* stdin, stdout, and stderr (-012 to specify which descriptors
* to leave open).
*
* NOTTY [-012] <command>
*/
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
static void usage(void);
int
main(int ac, char **av)
{
const char *opts = "";
int ttyfd;
int fd;
if (ac == 1)
usage();
if (av[1]) {
if (av[1][0] == '-') {
opts = av[1];
++av;
}
}
ttyfd = open("/dev/null", O_RDWR);
if (strchr(opts, '0') == NULL && ttyfd != 0)
dup2(ttyfd, 0);
if (strchr(opts, '1') == NULL && ttyfd != 1)
dup2(ttyfd, 1);
if (strchr(opts, '2') == NULL && ttyfd != 2)
dup2(ttyfd, 2);
if (ttyfd > 2)
close(ttyfd);
fd = open("/dev/tty", O_RDWR);
if (fd >= 0) {
ioctl(fd, TIOCNOTTY, 0);
close(fd);
}
if (fork() == 0) {
setsid();
exit(execvp(av[1], av + 1));
}
exit(0);
}
static void
usage(void)
{
fprintf(stderr, "notty [-012] command args ...\n");
exit(1);
}
ENDFILE
${cc_b} -o ./notty.bin ${TMPFILE}
${strip_b} ./notty.bin
${rm_b} -f ${TMPFILE}
notty="./notty.bin"
pgsql_b="${notty} -01 ${pgsql_b}"
pgsql_dump_b="${notty} -01 ${pgsql_dump_b}"
pgsql_vac_b="${notty} -01 ${pgsql_vac_b}"
else
${rm_b} -f ${notty}
${echo_b} "Cleaned up..."
fi
}
if [ "${mysql_do}" = "YES" ]
then
mysql_backup
fi
if [ "${file_do}" = "YES" ]
then
file_backup
fi
if [ "${pgsql_do}" = "YES" ]
then
if [ '$pgsql_p' != '' ]
then
notty 1
fi
pgsql_backup
if [ '$pgsql_p' != '' ]
then
notty 0
fi
fi
@andrew-azarov
Copy link
Author

MIT Licensed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment