4

I used to backup one partition to an external drive using grsync but now i have to backup different different folders to corresponding folders in External HDD. It would be helpful if they can be automated on every plug-in of HDD using corn or alike or with whatever app..

Thanks for your time.

Edit: I am not a big Pro in Coding so i may need the solution in a continuous way to apply it practically successfully. And i also need completely automatic solution if possible. This link may have the answer but because of it's discontinuous nature it is very difficult for me to filter the appropriate actions needed to get my desired work done.

Thanks again.

data9
  • 243

2 Answers2

0

Automatic Backup to External Disk Whenever Connected

Determine the ID_MODEL_ID=? and ID_VENDOR_ID=? of your external drive you want automatic backups to be done in with:

udevadm info -x /sys/class/block/sdb

(replace sdb with appropriate block device name.)

Now, create a udev .rules file with the following content as /etc/udev/rules.d/99-trigger-backup-to-external-disk.udev.rules :

SUBSYSTEM!="block", GOTO="label__my_rules_end"
KERNEL!="sd*", GOTO="label__my_rules_end"
ENV{DEVTYPE}!="disk", GOTO="label__my_rules_end"

For my SanDisk 3.2Gen1 64GB flash disk device:

ATTRS{idProduct}=="5590", ATTRS{idVendor}=="0781", GOTO="label__enlisted_devices"

ATTRS{idProduct}!="5590", ATTRS{idVendor}!="0781", GOTO="label__my_rules_end"

LABEL="label__enlisted_devices"

ACTION!="add", GOTO="label__my_rules_end"

ACTION=="add", SUBSYSTEM=="block", KERNEL=="sd*", ENV{DEVTYPE}=="disk", ATTRS{idProduct}=="5590", ATTRS{idVendor}=="0781", TAG+="systemd", ENV{SYSTEMD_USER_WANTS}+="backup_to_external_disk@dev-%k.target", GOTO="label__my_rules_end"

LABEL="label__my_rules_end"

In this file replace the integer values for ATTRS{idProduct} and ATTRS{idVendor} appropriately for your device obtained as above with udevadm info ... command.

Now, create $HOME/.config/systemd/user/ directory with:

mkdir -p "${HOME}/.config/systemd/user/"

Create a file ${HOME}/.config/systemd/user/backup_to_external_disk@.target and write the following content:

[Unit]
Description=Backup To External Disk - target unit for %I
Documentation=man:systemd.unit(5) man:systemd.exec(5) man:systemd.special(7) man:systemd.target(5)
StopWhenUnneeded=yes
Requires=backup_to_external_disk@%i.service
Before=backup_to_external_disk@%i.service
RefuseManualStart=true
RefuseManualStop=true

Create a file ${HOME}/.config/systemd/user/backup_to_external_disk@.service and write the following content:

[Unit]
Description=Backup To External Disk
Documentation=man:systemd.unit(5) man:systemd.exec(5) man:systemd.special(7) man:systemd.target(5)
ConditionPathExistsGlob=/sys/class/block/sd*
RefuseManualStart=true
RefuseManualStop=true

[Service] Type=exec ExecStart=-/bin/bash -c '/opt/backup_to_external_disk/bin/backup_to_external_disk.sh -d %i --backup'

Now, create the directory /opt/backup_to_external_disk/bin/ and executable file backup_to_external_disk.sh with:

sudo mkdir -p /opt/backup_to_external_disk/bin
touch /opt/backup_to_external_disk/bin/backup_to_external_disk.sh
chmod +x /opt/backup_to_external_disk/bin/backup_to_external_disk.sh

Now, write the following content to /opt/backup_to_external_disk/bin/backup_to_external_disk.sh script:

#!/bin/bash

declare __SCRIPT_NAME="${0##*/}" declare __SCRIPT_NAME_SH="${__SCRIPT_NAME%.sh}"

declare -i __FLAG__GUI_MODE=1 ## 0 = Non-GUI mode i.e. CLI mode; 1 = GUI mode

declare __DIR_TMP="/tmp/.${__SCRIPT_NAME_SH}" declare __LOG_MESSAGES="${__DIR_TMP}/msg.log"

declare __BLOCK_DEVICE_NAME_SYSTEMDSTYLE="" ## systemd escaped name of block device e.g. "dev-sda" declare __BLOCK_DEVICE_NAME="" ## name of block device e.g. "sda" declare __BLOCK_DEVICE_PATH="" ## device path e.g. "/dev/sda"

shopt -s huponexit _TrapHandle__HUP() { if [[ -f "${__LOG_MESSAGES}" ]] ; then _Write_Log "[_TrapHandle__HUP()] : The running terminal was closed, so the script '${__SCRIPT_NAME}' has to end unexpectedly." fi }

_TrapHandle__EXIT() { if [[ -f "${__LOG_MESSAGES}" ]] ; then _Write_Log "[_TrapHandle__EXIT()] : The script '${__SCRIPT_NAME}' is exiting now." fi }

trap _TrapHandle__HUP SIGHUP trap _TrapHandle__EXIT EXIT

function _Show_Help() { while read -r ; do echo "${REPLY}" done <<-__EOF Synoptis: ${__SCRIPT_NAME} [OPTION]

OPTIONS: -d Systemd-escaped device name of the device to be backuped into.

--backup
Initiate automatic backup from directory '\$HOME/Documents' to the configured
backup external disk in a directory called 'backup/Documents'.

-h, --help
Show this help.

__EOF }

function Write_Log() { echo "$( date +%Y-%m-%d%H%M%S ) | ${@}" >> "${__LOG_MESSAGES}" }

Execution begins:

if [[ ${#} -eq 0 ]] ; then _Show_Help exit 1 fi

if [[ ! -d "${__DIR_TMP}" ]] ; then if ! mkdir -p "${__DIR_TMP}" ; then echo "[ERROR] Could not create temporary directory. Terminate now." >&2 exit 1 fi fi

_Write_Log "---------- $(date) ----------" _Write_Log "Script '${__SCRIPT_NAME}' has already started and is processing." _Write_Log "Command line arguments: $@"

Parse the command-line arguments:

declare __SCRIPT_ARGS="" declare -i __SCRIPT_ARG_COUNT=${#} declare -a __OPERANDS=() declare __TASK="" ## check and call associated function

Assign a default task:

__TASK="action____show_help"

while [[ ${#} -gt 0 ]]; do __SCRIPT_ARGS="${1}" case "${__SCRIPT_ARGS}" in --backup) __TASK="action____perform_backup" shift ;; -d) ## The systemd escaped name for the block device: __BLOCK_DEVICE_NAME_SYSTEMDSTYLE="${2}" ## If unescaped path is specified, escape it in anticipation of a ## block device path: if [[ "${__BLOCK_DEVICE_NAME_SYSTEMDSTYLE}" =~ / ]] ; then __BLOCK_DEVICE_NAME_SYSTEMDSTYLE=$( systemd-escape --path "${__BLOCK_DEVICE_NAME_SYSTEMDSTYLE}" ) fi __BLOCK_DEVICE_NAME="${__BLOCK_DEVICE_NAME_SYSTEMDSTYLE##-}" __BLOCK_DEVICE_PATH="/${__BLOCK_DEVICE_NAME_SYSTEMDSTYLE//-//}" shift 2 ## shift past $1 and $2 . ;; -h|--help) __TASK="action____show_help" shift ;; ) __OPERANDS+=( "${1}" ) # save operands in array for later shift ## past operand parameter ;; esac done

Restore saved positional parameters.

if [[ ${#} -ne ${__SCRIPT_ARG_COUNT} ]]; then set -- "${__OPERANDS[@]}" fi

Excess operands must not be at the command line:

if [[ ${#} -gt 0 ]]; then echo "[ERROR] Some operands at the command line are not recognised." >&2 _Write_Log "[ERROR] Some operands at the command line are not recognised." echo "Exiting now." >&2 exit 1 fi

case "${__TASK}" in action____show_help) _Show_Help exit 0 ;; action____perform_backup) if [[ -z "${__BLOCK_DEVICE_NAME_SYSTEMDSTYLE}" && ! "${__BLOCK_DEVICE_NAME_SYSTEMDSTYLE}" =~ ^dev-sd[a-z]$ ]] ; then _Write_Log "[ERROR] Use option -d to specify the systemd instance name for the escaped block device path e.g. dev-sdb." exit 1 fi if [[ ! -b "${__BLOCK_DEVICE_PATH}" ]] ; then _Write_Log "[ERROR] The block device '${__BLOCK_DEVICE_PATH}' does not exist." exit 1 fi

    ##  Check GUI mode:
    if systemctl --quiet is-active graphical.target ; then
        __FLAG__GUI_MODE=1
        echo &quot;GUI mode is active.&quot;
        _Write_Log &quot;GUI mode is active.&quot;
    else
        __FLAG__GUI_MODE=0
    fi

    # echo &quot;The block device '${__BLOCK_DEVICE_PATH}' exists. Do you want to mount it and perform a backup? (Y/N)&quot;
    zenity --question --title=&quot;The block device '${__BLOCK_DEVICE_PATH}' exists.&quot; --text=&quot;Do you want to mount it and perform a backup from '${HOME}/Documents/' to 'backups/Documents' directory in the external disk?&quot;
    declare -i __ZENITY_REPLY_INT=${?}
    if [[ ${__ZENITY_REPLY_INT} -ne 0 ]] ; then
        _Write_Log &quot;You chose not to backup the device. Will exit now.&quot;
        exit 1
    fi
    _Write_Log &quot;You chose to backup the device. Will backup now.&quot;
    declare __BLOCK_DEVICE_PARTITION_PATH=&quot;${__BLOCK_DEVICE_PATH}1&quot;
    declare __MOUNT_POINT=&quot;&quot;
    __MOUNT_POINT=&quot;$( udisksctl mount -b &quot;${__BLOCK_DEVICE_PARTITION_PATH}&quot; )&quot;
    declare -i __RETURN_STATUS=${?}
    ## We need to obtain mount point as:
    __MOUNT_POINT=&quot;${__MOUNT_POINT#Mounted ${__BLOCK_DEVICE_PARTITION_PATH} at }&quot;
    if [[ ${__RETURN_STATUS} -eq 0 ]] ; then
        _Write_Log &quot;Successfully mounted ${__BLOCK_DEVICE_PARTITION_PATH} at ${__MOUNT_POINT} .&quot;
    else
        _Write_Log &quot;Failed to mount ${__BLOCK_DEVICE_PARTITION_PATH} .&quot;
        exit 1
    fi
    declare __BACKUP_DESTINATION=&quot;${__MOUNT_POINT}/backups/Documents&quot;
    if [[ ! -d &quot;${__BACKUP_DESTINATION}&quot; ]] ; then
        if ! mkdir -p &quot;${__BACKUP_DESTINATION}&quot; ; then
            _Write_Log &quot;Could not create backup destination '${__BACKUP_DESTINATION}' directory.&quot;
           exit 1
        fi
    else
        _Write_Log &quot;Backup destination '${__BACKUP_DESTINATION}' exists.&quot;
    fi
    _Write_Log &quot;Using backup command: rsync -a '${HOME}/Documents/' '${__BACKUP_DESTINATION}'&quot;
    if [[ -d &quot;${__BACKUP_DESTINATION}&quot; ]] ; then
        rsync -a &quot;${HOME}/Documents/&quot; &quot;${__BACKUP_DESTINATION}&quot; | zenity --progress --pulsate --auto-close --title=&quot;DO NOT EJECT DEVICE ${__BLOCK_DEVICE_PARTITION_PATH}.&quot; --text=&quot;Backup is in progress...&quot;
        _Write_Log &quot;Backup with rsync completed with status=${PIPESTATUS[0]}.&quot;
        zenity --question --title &quot;Backup Done :: Unmount Device?&quot; --text=&quot;The backup operation using rsync command completed with status=${PIPESTATUS[0]}. Do you want to unmount the device?&quot;
        __RETURN_STATUS=${?}
        if [[ ${__RETURN_STATUS} -eq 0 ]] ; then
            udisksctl unmount -b &quot;${__BLOCK_DEVICE_PARTITION_PATH}&quot;
            __RETURN_STATUS=${?}
            if [[ ${__RETURN_STATUS} -ne 0 ]] ; then
                _Write_Log &quot;Unmounting the device ${__BLOCK_DEVICE_PARTITION_PATH} failed.&quot;
                zenity --warning --title &quot;Unmount failed!&quot; --text=&quot;The udisksctl unmount -b ${__BLOCK_DEVICE_PARTITION_PATH} command failed.&quot;
            else
                _Write_Log &quot;Unmounted the device ${__BLOCK_DEVICE_PARTITION_PATH} successfully.&quot;
                zenity --info --title &quot;Unmount done.&quot; --text=&quot;The udisksctl unmount -b ${__BLOCK_DEVICE_PARTITION_PATH} command completed successfully.&quot;
            fi
        fi
    else
        _Write_Log &quot;The backup destination '${__BACKUP_DESTINATION}' does not exist.&quot;
        exit 1
    fi
    ;;

esac exit 0

End of the script.

Now, reboot the system or run the following command:

systemctl --user daemon-reload ; sudo systemctl reload udev

Now, each time you connect the configured device to the system, you will be prompted for a backup.

rusty
  • 16,327
0

Here's an answer from our friends over at Unix Stackflow: https://unix.stackexchange.com/questions/66749/how-to-auto-sync-with-a-plugged-in-usb-mass-storage-device

It appears the most promising tool for this is DirSync Pro (apparently OSS).

Mordoc
  • 2,064
  • Thanks for the reply, but it does not seem to answer my question directly or rhythmically, it may does so but fragmentarily so to make it difficult for me to apply it to get desired result. Dirsync Pro also does not have any automatic backup for Ext. HDDs feature available. http://www.dirsyncpro.org/features.html – data9 Jan 28 '14 at 05:44