Skip to content
Snippets Groups Projects
comp-backup.sh 7.61 KiB
Newer Older
  • Learn to ignore specific revisions
  • efer's avatar
    efer committed
    #!/bin/bash
    #
    # Copyright (c) 2018 Ejner Fergo efer@dtu.dk
    #
    # License: 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 3 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.
    #
    
    # Main Variables
    SCRIPTNAME="comp-backup"
    
    efer's avatar
    efer committed
    VERSION=6
    
    efer's avatar
    efer committed
    LOGNAME="backup_logfile"
    
    efer's avatar
    efer committed
    TARGETNODE="backup.compute.dtu.dk"
    
    efer's avatar
    efer committed
    HOST=$(hostname -s)
    H=$HOME
    BIN_DIR="$H/bin"
    
    # Banner
    clear
    echo "#-------------------------------#"
    echo "#   DTU Compute backup script   #"
    echo "#-------------------------------#"
    echo
    echo "This script will setup a backup routine for you"
    echo "Backup server is: $TARGETNODE"
    echo
    
    # User Specific Variables
    USER=$(whoami)
    echo "Enter your DTU username [$USER]:"
    read ANS
    case $ANS in
        "")
            RUSER=$USER ;;
        *)
            RUSER=$ANS ;;
    esac
    
    efer's avatar
    efer committed
    RHOME=/home/$RUSER
    
    efer's avatar
    efer committed
    SCRIPTNAME="$SCRIPTNAME-$RUSER"
    
    # SUDO
    chksudo() {
        echo "Check sudo"
        sudo -l &>/dev/null
        if [ $? -ne 0 ]; then
            echo "You need sudo rights to continue."
            exit 1
        fi
        echo "[sudo] OK"
        }
    
    # Platform Specific Variables
    HOST_OS=$(uname -s)
    if [ $HOST_OS = 'Darwin' ]; then
        UNIT_DIR="$H/Library/LaunchAgents"
        [ ! -d $UNIT_DIR ] && mkdir -p $UNIT_DIR
        CONF_DIR="$H/Library/$SCRIPTNAME"
        $(which osascript &>/dev/null)
        if [ $? -eq 0 ]; then
            NOTIFY0='osascript -e "display notification \"Backup done\" with title \"FYI\""'
            NOTIFY1='osascript -e "display notification \"Backup did not complete\" with title \"FYI\""'
        fi
        pexcl=($H/Movies
              $H/.Trash
              $H/Library
              *.dmg
              .DS_Store)
    elif [ $HOST_OS = 'Linux' ]; then
        CONF_DIR="$H/.config/$SCRIPTNAME"
        $(which notify-send &>/dev/null)
        if [ $? -eq 0 ]; then
            NOTIFY0='notify-send "Backup done"'
            NOTIFY1='notify-send "Backup did not complete"'
        fi
    
    efer's avatar
    efer committed
        pexcl=($H/Videos
        	   $H/.dbus)
    
    efer's avatar
    efer committed
        # SYSTEMD
        $(which systemctl &>/dev/null)
        if [ $? -ne 0 ]; then
            SYSTEMD=0
            echo "No systemd - Backup will need to be run manually"
        else
            SYSTEMD=1
    
    efer's avatar
    efer committed
            sysd_ver=$(systemctl --version |grep -o '\s[0-9][0-9][0-9]\s')
    
    efer's avatar
    efer committed
            if [ $sysd_ver -lt 220 ]; then
                echo "No 'systemctl --user' capability"
                echo "Installing system wide"
                chksudo
                dosudo="sudo"
                UNIT_DIR="/etc/systemd/system"
            else
                UNIT_DIR="$H/.config/systemd/user"
                [ ! -d $UNIT_DIR ] && mkdir -p $UNIT_DIR
                douser="--user"
            fi
        fi
    else
        echo "OS not supportet"
        exit 1
    fi
    incl=($H/)
    excl=(
         $H/Downloads
         $H/Music
         $H/anaconda*
         $H/.conda
         $H/.cache
         $H/.local
    
    efer's avatar
    efer committed
         *.vdi
         *.vmdk
         *.iso
         )
    
    # Initial Setup
    if [ -x $BIN_DIR/$SCRIPTNAME ]; then
        ver=$(grep -o [0-9]$ $BIN_DIR/$SCRIPTNAME)
        if [ $ver -lt $VERSION ]; then
            echo "New version will be installed"
            if [ $HOST_OS = 'Linux' ]; then
                if [ $SYSTEMD = 1 ]; then
                    $dosudo systemctl $douser stop $SCRIPTNAME.timer &>/dev/null
                    $dosudo systemctl $douser disable $SCRIPTNAME.timer &>/dev/null
                fi
            fi
        else
            echo "Backup script already installed"
            exit 0
        fi
    elif [ ! -d $BIN_DIR ]; then
        mkdir $BIN_DIR 
    fi
    $(echo $PATH | grep -o $BIN_DIR &>/dev/null)
    if [ $? -ne 0 ]; then
    
    efer's avatar
    efer committed
        if [ $SHELL == '/bin/bash' ]; then
            echo -e "\nexport PATH=$PATH:$BIN_DIR" >> $H/.bash_profile
            source $H/.bash_profile
        elif [ $SHELL == '/bin/zsh' ]; then
            echo -e "\nexport PATH=$PATH:$BIN_DIR" >> $H/.zprofile
            source $H/.zprofile
        else
            echo -e "\nexport PATH=$PATH:$BIN_DIR" >> $H/.profile
            source $H/.profile
        fi
    
    efer's avatar
    efer committed
    fi
    if [ ! -d $CONF_DIR ]; then
        mkdir -p $CONF_DIR 
        echo "# Files to include" > $CONF_DIR/include
        for i in ${incl[*]}; do
            echo $i >> $CONF_DIR/include
        done
        echo "# Files to exclude" > $CONF_DIR/exclude
        for e in ${excl[*]}; do
            echo $e >> $CONF_DIR/exclude
        done
        for p in ${pexcl[*]}; do
            echo $p >> $CONF_DIR/exclude
        done
    fi
    
    # SSH
    echo "Check ssh"
    grep $TARGETNODE $H/.ssh/known_hosts &>/dev/null
    if [ $? -ne 0 ]; then
        if [ ! -d ~/.ssh ]; then
            mkdir ~/.ssh
            chmod 700 ~/.ssh
        fi
        ssh-keyscan -H -t ecdsa $TARGETNODE 2>/dev/null|grep ^[^#] >> ~/.ssh/known_hosts
    fi
    
    SSHKEY=~/.ssh/$SCRIPTNAME
    if [ -f $SSHKEY ]; then
        ssh -o BatchMode=yes -i $SSHKEY $RUSER@$TARGETNODE "grep -o $USER@$HOST .ssh/authorized_keys" &>/dev/null
        if [ $? -ne 0 ]; then
            echo "Installing public key"
            ssh-copy-id -i $SSHKEY $RUSER@$TARGETNODE &>/dev/null
        else
            echo "[ssh] OK"
        fi
    else
        echo "Creating SSH keys"
        ssh-keygen -q -f $SSHKEY -N '' &>/dev/null
        ssh-copy-id -i $SSHKEY $RUSER@$TARGETNODE &>/dev/null
    fi
    
    # Create Backup Dir
    echo "Checking for backup dir..."
    ssh -i $SSHKEY $RUSER@$TARGETNODE ls -d $RHOME/$HOST &>/dev/null
    if [ $? = 0 ]; then
        ssh -i $SSHKEY $RUSER@$TARGETNODE ls $RHOME/$HOST/$LOGNAME &>/dev/null
        if [ $? = 0 ]; then
            ssh -i $SSHKEY $RUSER@$TARGETNODE mv $RHOME/$HOST/$LOGNAME $RHOME/$HOST/old_install.$(date +%Y-%m-%d)
        fi
        echo "OK"
    else
        ssh -i $SSHKEY $RUSER@$TARGETNODE "mkdir $RHOME/$HOST && chmod 700 $RHOME/$HOST"
        if [ $? = 0 ]; then
            echo "Created backup dir"
        else
            echo "Failed to create backup dir"
            exit 1
        fi
    fi
    
    # Script & Daemon Files
    echo "Writing files"
    
    TMP="$H/.local/tmp"
    if [ ! -d $TMP ]; then
        mkdir -p $TMP
    fi
    LOG=$TMP/$LOGNAME-$RUSER
    
    cat > $BIN_DIR/$SCRIPTNAME << EOF
    #!/bin/bash
    # version=$VERSION
    
    # Log check
    logcheck(){
        lsize=\$(du $LOG|awk '{print \$1}')
        if [ \$lsize -gt 2048 ]; then
            scp -i $SSHKEY $LOG $RUSER@$TARGETNODE:$RHOME/$HOST/$LOGNAME-$RUSER.\$(date +%Y-%m-%d)
            mv $LOG $LOG.\$(date +%Y-%m-%d)
        fi
    }
    
    # Main
    if [ -f $LOG ]; then
        logcheck
    fi
    rsync -arRx -e "ssh -i $SSHKEY" \
    --files-from=$CONF_DIR/include \
    --exclude-from=$CONF_DIR/exclude \
    --delete-excluded --delete-before \
    --log-file=$LOG \
    / $RUSER@$TARGETNODE:$RHOME/$HOST/
    
    if [ \$? -eq 0 ]; then
        echo "Backup ok"
        $NOTIFY0
    else
        echo "Backup failed"
        $NOTIFY1
    fi
    
    # Log update
    rsync -a -e "ssh -i $SSHKEY" $TMP/$LOGNAME-$RUSER $RUSER@$TARGETNODE:$RHOME/$HOST/$LOGNAME
    EOF
    chmod +x $BIN_DIR/$SCRIPTNAME
    
    if [ $HOST_OS = 'Darwin' ]; then
    
    cat > $UNIT_DIR/com.dtucompute.backup.plist << EOF
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    
    <dict>
    	<key>Label</key>
    	<string>com.dtucompute.backup</string>
    	<key>ProgramArguments</key>
    	<array>
    		<string>$BIN_DIR/$SCRIPTNAME</string>
    	</array>
    	<key>StartInterval</key>
    	<integer>10800</integer>
    </dict>
    
    </plist>
    EOF
    
    elif [ $SYSTEMD = 1 ]; then
    
    $dosudo bash -c "cat > $UNIT_DIR/$SCRIPTNAME.timer" << EOF
    [Unit]
    Description=$SCRIPTNAME timer
    
    [Timer]
    OnBootSec=5min
    OnUnitActiveSec=3h
    Unit=$SCRIPTNAME.service
    
    [Install]
    WantedBy=timers.target
    EOF
    
    $dosudo bash -c "cat > $UNIT_DIR/$SCRIPTNAME.service" << EOF
    [Unit]
    Description=DTU Compute backup script
    After=network-online.target
    Wants=network-online.target
    
    [Service]
    Type=simple
    ExecStart=$BIN_DIR/$SCRIPTNAME
    
    [Install]
    WantedBy=default.target
    EOF
    
    $dosudo systemctl $douser enable $SCRIPTNAME.timer &>/dev/null
    fi
    
    # Finish
    echo "Backup script installed"
    echo