#!/bin/bash # # ---------------------------------------------------------------------- # # Description: This script creates a backup TAR archive # of modified files from RPM or debian packages. You can # specify additional files or folders to backup, from # within the Midnight Commander menu. Handy if you want to # carry your config files around ALL the time # # Author: Maccus # # Revision: 080516-01 # # Requires: This script requires certain programs to # ensure correct execution: tar, rpm, debsums, mc # # This script has been written and tested on # Ubuntu Linux 10.04 and Debian Testing (Wheezy) # # ---------------------------------------------------------------------- # # Usage: Place the script in "/usr/local/bin", do a # # "chmod +x /usr/local/bin/system-make-backup" # # Then, as root, run: # # "system-make-backup --bkpdir /path/to/your/backup/folder" # # The first time the Midnight Commander menu entries # will be created. You can then select the files/folders # you want to backup with Midnight Commander: select one # or more files/folders, with the "Insert" key then press # "F2" and select: # # "Mark (current/tagged) file(s) for backup". # # A list of files/dirs that you want to backup will then # be created in /etc/make-backup. If this list is created # you can run the script any time to make a backup archive. # # The script is also suitable to run as a cron job. # # ---------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # ---------------------------------------------------------------------- # # Uncomment for debugging # # set -x # Start script echo -e "\n\033[1;33mSTATUS\033[0m: Script \"$(basename $0)\" is gestart...\n" NICEVAL="-19" # Check to see if we are root. if [ "${UID}" != "0" ]; then echo -e "You must be root !!\n" sleep 2 exit 1 fi # Destination if [ "$1" != "--bkpdir" -o -z "$2" ]; then echo -e "You must specify a destination directory with --bkpdir !!\n" echo -e "Usage: $0 --bkpdir /path/to/backup/folder\n" echo -e "If the folder does not exist, it will be created.\n" sleep 5 exit 1 fi # Check to see if the required package are installed [ -e "/etc/debian_version" ] && REQS="debsums" || REQS="rpm" for BINARY in ${REQS} tar mc ; do if ! which ${BINARY} > /dev/null ; then echo -e "This script will not run without \"${BINARY}\"" echo -e "Please install\"${BINARY}\" and try again." echo -e "Aborting now..." sleep 5 exit 1 fi done # Locations / names ETCDIR="/etc/scriptconfig" FILELIST="${ETCDIR}/system-make-backup-$(hostname -f).conf" GLOBAL_MCMENU="/etc/mc/mc.menu" MCMENU="${HOME}/.mc/menu" MCDIR="$(dirname ${MCMENU})" BKPDIR="$2" ARCHIVE="backup-$(hostname -s)-system-$(date "+%y%m%d")" # Create if non existant [ -d "${ETCDIR}" ] || mkdir -p "${ETCDIR}" [ -f "${FILELIST}" ] || touch "${FILELIST}" [ -d "${MCDIR}" ] || mkdir -p "${MCDIR}" [ -f "${MCMENU}" ] || touch "${MCMENU}" [ -d "${BKPDIR}" ] || mkdir -p "${BKPDIR}" # Add file selector to MC menufile if ! grep -qe "MAKE-BACKUP" "${GLOBAL_MCMENU}" -o ! grep -qe "MAKE-BACKUP" "${MCMENU}" ; then cat >> "${MCMENU}" < "${ETCDIR}/system-make-backup-\$(hostname -f).conf" FILE="\$(echo %d/%f | sed "s|\/\/|/|")" if ! cat "\${FILELIST}" | grep -q "^\${FILE}$" ; then echo "\${FILE}" >> "\${FILELIST}" cat "\${FILELIST}" | sort -do "\${FILELIST}.new" mv "\${FILELIST}.new" "\${FILELIST}" echo -e "\033[1;32mADDED\033[0m \${FILE} to \${FILELIST}" elif cat "\${FILELIST}" | grep -q "^\${FILE}$" ; then echo -en "File is already in the backuplist.\n -- Remove file from the list ? [y/N]: " read YESNO if [ "\${YESNO}" = "y" ]; then cat "\${FILELIST}" | grep -v "^\${FILE}$" > "\${FILELIST}.new" mv "\${FILELIST}.new" "\${FILELIST}" echo -e "\033[1;31mREMOVED\033[0m \${FILE} from \${FILELIST}" fi fi + t r d & t t Mark tagged files for backup FILELIST="${ETCDIR}/system-make-backup-\$(hostname -f).conf" [ -d "${ETCDIR}" ] || mkdir -p "${ETCDIR}" [ -f "${ETCDIR}/system-make-backup-\$(hostname -f).conf" ] || > "${ETCDIR}/system-make-backup-\$(hostname -f).conf" for FILE in %u ; do FILE="\$(echo %d/\${FILE} | sed "s|\/\/|/|")" if ! cat "\${FILELIST}" | grep -q "^\${FILE}$" ; then echo "\${FILE}" >> "\${FILELIST}" cat "\${FILELIST}" | sort -do "\${FILELIST}.new" mv "\${FILELIST}.new" "\${FILELIST}" echo -e "\033[1;32mADDED\033[0m \${FILE} to \${FILELIST}" elif cat "\${FILELIST}" | grep -q "^\${FILE}$" ; then echo -en "File is already in the backuplist.\n -- Remove file from the list ? [y/N]: " read YESNO if [ "\${YESNO}" = "y" ]; then cat "\${FILELIST}" | grep -v "^\${FILE}$" > "\${FILELIST}.new" mv "\${FILELIST}.new" "\${FILELIST}" echo -e "\033[1;31mREMOVED\033[0m \${FILE} to \${FILELIST}" fi fi done EOF echo -e "Added menu entry to \"${MCMENU}\".\n" echo -e "Now you are ready to go. Just select some files in Midnight Commander" echo -e "with the \"Insert\" key and press \"F2\" to add them to the backup list.\n" echo -e "After that you can restart this script with:\n" echo -e "\"$0 --bkpdir /path/to/your/backupfolder\"\n" echo -e "Then the files in the list will be backed up to a TAR archive\n" sleep 5 exit 0 fi # Start the heavy stuff echo -e "Starting system backup. The archive will be written to ${BKPDIR}/${ARCHIVE}.tar.bz2\n" # Debian or RPM-based checks. # Check to see if there are modified files # from packages, and add them to the list. echo -e "Searching for modified system files. This may take a while...\n" if [ -e "/etc/debian_version" ]; then nice ${NICEVAL} debsums -ca 2> "/dev/null" | sed "s|^[ ]\/|/|" >> "${FILELIST}" else nice ${NICEVAL} rpm -Va | grep '^..5' | sed "s/^...........//" | sed "s|^[ ]\/|/|" >> "${FILELIST}" fi # Sort list and remove duplicate entries. # Remove lines that begin with a space cat "${FILELIST}" | sed "s|^[ ]\/|/|" | sort -do "${FILELIST}.tmp" uniq "${FILELIST}.tmp" "${FILELIST}" rm -f "${FILELIST}.tmp" # See if there are files listed that no longer exist, and remove them. cat "${FILELIST}" | while read FILE ; do if [ ! -e "${FILE}" ]; then grep -v "^${FILE}$" "${FILELIST}" > "${FILELIST}.new" mv "${FILELIST}.new" "${FILELIST}" echo -e "Removed \"${FILE}\" from \"${FILELIST}\"" fi done # Generate the archive echo -e "\nAdding files to archive \"${BKPDIR}/${ARCHIVE}.tar\"...\n" sleep 2 # Tar writes files with the same name to the end # of an archive and does not delete the older versions. # So first remove previous backups with the same name. [ -f "${BKPDIR}/${ARCHIVE}.tar" ] && rm -f "${BKPDIR}/${ARCHIVE}.tar" # I put this in a while loop to handle filenames with spaces nice ${NICEVAL} tar cfT "${BKPDIR}/${ARCHIVE}.tar" "/dev/null" cat "${FILELIST}" | while read FILE ; do FILE="$(echo -e "${FILE}" | sed "s|[ ]|\\\\ |g")" nice ${NICEVAL} tar rvf "${BKPDIR}/${ARCHIVE}.tar" "${FILE}" done echo -e "\nCompressing archive \"${BKPDIR}/${ARCHIVE}.tar\"...\n" nice ${NICEVAL} bzip2 -f -9 "${BKPDIR}/${ARCHIVE}.tar" # Remove old backup(s) after 28 days if [ -f "${BKPDIR}/${ARCHIVE}.tar.bz2" ]; then echo -e "\nSystem backup \"${BKPDIR}/${ARCHIVE}.tar.bz2\" sucessfully written.\n" find ${BKPDIR}/ -regex ".*backup-$(hostname -s)-system-.*[.]tar[.]bz2" \ -mtime +28 \ -type f \ -print | xargs -r rm -f -v else echo -e "\nCreation of system backup \"${BKPDIR}/${ARCHIVE}.tar.bz2\" FAILED!.\n" fi sleep 30 exit 0