“Moment, bevor ich die Config ändere, noch schnell ne Sicherungskopie von der original Datei machen. cp yum.conf yum.conf-201302 ... .. äh, welches Datum haben wir heute? So ein mist, na dann eben cp yum.conf yum.conf-$(date +%Y%... Großes M oder kleines m? Ich kann’s mir einfach nicht merken, außerdem zuviel Tipparbeit. Da muss was einfacheres her.”

.. und hier ist mein, zugegeben sehr einfaches aber wie ich finde recht nützliches bash-Skript für die Lösung des “Problems”.

Es hat den einfallsreichem Namen: backup     ;)

Meine Kollegen und ich verwendes es mittlerweile immer und überall. Auch in anderen Skripten, die mit Dateiänderungen arbeiten, kommt backup mit der -k Option zum Einsatz.

Kleines Beipiel

[root@myhost etc]# backup yum.conf
[root@myhost etc]# ls -l yum.conf*
-rw-r--r-- 1 root root 346 May 22 2012 yum.conf
-rw-r--r-- 1 root root 346 May 22 2012 yum.conf.20130207-084855
[root@myhost etc]# backup
usage: ./backup [-k <num> ] [-yv] file_to_backup [file_to_backup...]
options:
-k keep last backups and remove older files
-y assume 'yes' if backup a directory
-v verbose
[root@myhost etc]#

Features
  • Sicherungskopien von mehreren Dateien und/oder Verzeichnissen erstellen
  • Automatisches löschen alter Sicherungen mit der -k Option (nach dem Erstellen von Neuen).
Download und Installation

Einfach das Skript kopieren und irgendwo in den $PATH legen. Fertig.

Hier das backup Skript:

#!/bin/bash
#
# Creates a copy with timestamp of the file(s) given in argument.
# Optionally removes old copies
#
# by sascha.nowak@dfs.de
#

KEEPNUM=0        # 0 = disabled

function printhelp() {
        echo "usage:  $0 [-k <num>] [-yv] file_to_backup [file_to_backup...]" >&2
        echo "options:" >&2
        echo "      -k    keep last <num> backups and remove older files" >&2
        echo "      -y    assume 'yes' if backup a directory" >&2
        echo "      -v    verbose" >&2
        exit 1
}

[ "$1" == "" ] && printhelp

while getopts ":k:yvh" opt
do
        case $opt in
                k)
                        [ ${OPTARG:0:1} = "=" ] && KEEPNUM=${OPTARG/=} || KEEPNUM=$OPTARG
                        ;;
                y)
                        YES="y"
                        ;;
                v)
                        VERBOSE="v"
                        ;;
                *)
                        printhelp
                        ;;
        esac
done

shift $(($OPTIND-1))

FILENAMES=$*

[[ $KEEPNUM == [0-9]* ]] || printhelp


# pre check
ERROR=0
for FILENAME in $FILENAMES; do

        if [ ! -e $FILENAME ]; then
                echo "file not found or unsupported filetype: $FILENAME" >&2
                ERROR=1
        fi
        if [ -L $FILENAME ]; then
                echo "file is a symlink: $FILENAME" >&2
                ERROR=1
        fi
        if [ -d $FILENAME -a $ERROR != 1 ] ; then
                if [ "$YES" != "y" ]; then
                        echo -n "Do you want to backup the whole directory $FILENAME? [Y/n] "
                        read YN
                        if [ "$YN" == 'n' ] ; then
                                echo OK, nothing backuped >&2
                                exit 1
                        else
                                YES=y
                        fi
                fi
        fi
done
if [ "$ERROR" == 1 ] ; then
        echo 'Operation stopped because of previous errors. Nothing backuped!' >&2
        exit 1
fi



# copy files
for FILENAME in $FILENAMES; do
        # evtl / am Ende entfernen
        FILENAME=$(echo $FILENAME | sed 's#/$##')
        cp -pr$VERBOSE $FILENAME $FILENAME.`date +%Y%m%d-%H%M%S`
        RETVAL=$?
        if [ "$RETVAL" -ne 0 ] ; then
                echo Copy error at file: $FILENAME >&2
                exit $RETVAL
        fi
done

# remove old files
if [ $KEEPNUM -gt 0 ]; then
        for FILENAME in $FILENAMES; do
                # evtl / am Ende entfernen
                FILENAME=$(echo $FILENAME | sed 's#/$##')
                I=0
                for FILE in `ls -dr $FILENAME.????????-??????`; do
                        I=$(( $I + 1 ))
                        [ $I -gt $KEEPNUM ] && rm -rf$VERBOSE $FILE
                done
        done
fi

Für Ideen und Anmerkungen bin ich offen.