RSync only if filesystem is mounted
Asked Answered
D

6

9

I want to setup a cron job to rsync a remote system to a backup partition, something like:

bash -c 'rsync -avz --delete --exclude=proc --exclude=sys root@remote1:/ /mnt/remote1/'

I would like to be able to "set it and forget it" but what if /mnt/remote1 becomes unmounted? (After a reboot or something) I'd like to error out if /mnt/remote1 isn't mounted, rather than filling up the local filesystem.

Edit:
Here is what I came up with for a script, cleanup improvements appreciated (especially for the empty then ... else, I couldn't leave them empty or bash errors)

#!/bin/bash

DATA=data
ERROR="0"

if cut -d' ' -f2 /proc/mounts | grep -q "^/mnt/$1\$"; then
    ERROR=0
else
    if mount /dev/vg/$1 /mnt/$1; then
        ERROR=0
    else
        ERROR=$?
        echo "Can't backup $1, /mnt/$1 could not be mounted: $ERROR"
    fi
fi

if [ "$ERROR" = "0" ]; then
    if cut -d' ' -f2 /proc/mounts | grep -q "^/mnt/$1/$DATA\$"; then
        ERROR=0
    else
        if mount /dev/vg/$1$DATA /mnt/$1/data; then
            ERROR=0
        else
            ERROR=$?
            echo "Can't backup $1, /mnt/$1/data could not be mounted."
        fi
    fi
fi

if [ "$ERROR" = "0" ]; then
    rsync -aqz --delete --numeric-ids --exclude=proc --exclude=sys \
        root@$1.domain:/ /mnt/$1/
    RETVAL=$?
    echo "Backup of $1 completed, return value of rsync: $RETVAL"
fi
Darindaring answered 26/8, 2008 at 3:37 Comment(0)
D
5
if cut -d' ' -f2 /proc/mounts | grep '^/mnt/remote1$' >/dev/null; then
    rsync -avz ...
fi

Get the list of mounted partitions from /proc/mounts, only match /mnt/remote1 (and if it is mounted, send grep's output to /dev/null), then run your rsync job.

Recent greps have a -q option that you can use instead of sending the output to /dev/null.

Dempstor answered 26/8, 2008 at 3:43 Comment(0)
K
11

mountpoint seems to be the best solution to this: it returns 0 if a path is a mount point:

#!/bin/bash
if [[ `mountpoint -q /path` ]]; then
    echo "filesystem mounted"
else
    echo "filesystem not mounted"
fi

Found at LinuxQuestions.

Kneeland answered 26/8, 2010 at 14:39 Comment(1)
except it's better to use ! mountpoint -q /dest || rsync -a /source/ /destTautomer
D
5
if cut -d' ' -f2 /proc/mounts | grep '^/mnt/remote1$' >/dev/null; then
    rsync -avz ...
fi

Get the list of mounted partitions from /proc/mounts, only match /mnt/remote1 (and if it is mounted, send grep's output to /dev/null), then run your rsync job.

Recent greps have a -q option that you can use instead of sending the output to /dev/null.

Dempstor answered 26/8, 2008 at 3:43 Comment(0)
C
3

A quick google led me to this bash script that can check if a filesystem is mounted. It seems that grepping the output of df or mount is the way to go:

if df |grep -q '/mnt/mountpoint$'
    then
        echo "Found mount point, running task"
        # Do some stuff
    else
        echo "Aborted because the disk is not mounted"
        # Do some error correcting stuff
        exit -1
fi
Clubbable answered 26/8, 2008 at 3:42 Comment(0)
Q
1
  1. Copy and paste the script below to a file (e.g. backup.sh).
  2. Make the script executable (e.g. chmod +x backup.sh)
  3. Call the script as root with the format backup.sh [username (for rsync)] [backup source device] [backup source location] [backup target device] [backup target location]

!!!ATTENTION!!! Don't execute the script as root user without understanding the code!

I think there's nothing to explain. The code is straightforward and well documented.

#!/bin/bash

##
## COMMAND USAGE: backup.sh [username] [backup source device] [backup source location] [backup target device] [backup target location]
##
## for example: sudo /home/manu/bin/backup.sh "manu" "/media/disk1" "/media/disk1/." "/media/disk2" "/media/disk2"
##

##
## VARIABLES
##

# execute as user
USER="$1"

# Set source location
BACKUP_SOURCE_DEV="$2"
BACKUP_SOURCE="$3"

# Set target location
BACKUP_TARGET_DEV="$4"
BACKUP_TARGET="$5"

# Log file
LOG_FILE="/var/log/backup_script.log"

##
## SCRIPT
##

function end() {
    echo -e "###########################################################################\
#########################################################################\n\n" >> "$LOG_FILE"
    exit $1
}

# Check that the log file exists
if [ ! -e "$LOG_FILE" ]; then
        touch "$LOG_FILE"
    chown $USER "$LOG_FILE"
fi

# Check if backup source device is mounted
if ! mountpoint "$BACKUP_SOURCE_DEV"; then
        echo "$(date "+%Y-%m-%d %k:%M:%S") - ERROR: Backup source device is not mounted!" >> "$LOG_FILE"
    end 1
fi

# Check that source dir exists and is readable.
if [ ! -r  "$BACKUP_SOURCE" ]; then
        echo "$(date "+%Y-%m-%d %k:%M:%S") - ERROR: Unable to read source dir." >> "$LOG_FILE"
        echo "$(date "+%Y-%m-%d %k:%M:%S") - ERROR: Unable to sync." >> "$LOG_FILE"
    end 1
fi

# Check that target dir exists and is writable.
if [ ! -w  "$BACKUP_TARGET" ]; then
        echo "$(date "+%Y-%m-%d %k:%M:%S") - ERROR: Unable to write to target dir." >> "$LOG_FILE"
        echo "$(date "+%Y-%m-%d %k:%M:%S") - ERROR: Unable to sync." >> "$LOG_FILE"
    end 1
fi

# Check if the drive is mounted
if ! mountpoint "$BACKUP_TARGET_DEV"; then
        echo "$(date "+%Y-%m-%d %k:%M:%S") - WARNING: Backup device needs mounting!" >> "$LOG_FILE"

        # If not, mount the drive
        if mount "$BACKUP_TARGET_DEV" > /dev/null 2>&1 || /bin/false; then
                echo "$(date "+%Y-%m-%d %k:%M:%S") - Backup device mounted." >> "$LOG_FILE"
        else
                echo "$(date "+%Y-%m-%d %k:%M:%S") - ERROR: Unable to mount backup device." >> "$LOG_FILE"
                echo "$(date "+%Y-%m-%d %k:%M:%S") - ERROR: Unable to sync." >> "$LOG_FILE"
        end 1
        fi
fi

# Start entry in the log
echo "$(date "+%Y-%m-%d %k:%M:%S") - Sync started." >> "$LOG_FILE"

# Start sync
su -c "rsync -ayhEAX --progress --delete-after --inplace --compress-level=0 --log-file=\"$LOG_FILE\" \"$BACKUP_SOURCE\" \"$BACKUP_TARGET\"" $USER
echo "" >> "$LOG_FILE"

# Unmount the drive so it does not accidentally get damaged or wiped
if umount "$BACKUP_TARGET_DEV" > /dev/null 2>&1 || /bin/false; then
    echo "$(date "+%Y-%m-%d %k:%M:%S") - Backup device unmounted." >> "$LOG_FILE"
else
    echo "$(date "+%Y-%m-%d %k:%M:%S") - WARNING: Backup device could not be unmounted." >> "$LOG_FILE"
fi

# Exit successfully
end 0
Quicksand answered 26/2, 2015 at 20:39 Comment(0)
P
0

I am skimming This but I would think you would rather rsync -e ssh and setup the keys to accept the account.

Purgatorial answered 3/6, 2014 at 17:34 Comment(0)
E
0

an improvement to existing answers would be to use .. like this:
rsync [opts] /mnt/source/ /mnt/target/.somedirectory/../

first mkdir /mnt/{source,target}/.empty before first run (or pick a folder you will never delete from source and mkdir it in target), then it should only work if target is mounted, otherwise the operation will fail when trying to traverse the path
hopefully the behavior never changes, you should verify it still works like that

if source is a mountpoint, --delete is dangerous, as it could become unmounted, deleting the entire target, so the same approach should be used for source:
rsync [opts] /mnt/source/.somedirectory/../ /mnt/target/.somedirectory/../

Euraeurasia answered 5/3 at 4:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.