我以前使用 grsync 将一个分区备份到外部驱动器,但现在我必须将不同的文件夹备份到外部硬盘中的相应文件夹。如果可以使用 corn 或类似程序或任何应用程序在硬盘的每个插件上自动执行这些操作,那将会很有帮助。
谢谢你的时间。
编辑:我不是编码方面的专家,所以我可能需要以连续的方式解决问题才能成功应用它。如果可能的话,我还需要完全自动化的解决方案。此链接可能有答案,但由于它的不连续性,我很难筛选出完成我想要的工作所需的适当的操作。
再次感谢。
答案1
以下是来自 Unix Stackflow 的朋友的回答:https://unix.stackexchange.com/questions/66749/how-to-auto-sync-with-a-plugged-in-usb-mass-storage-device
看来最有前途的工具是 DirSync Pro(显然是 OSS)。
答案2
连接时自动备份到外部磁盘
确定要自动备份的外部驱动器的以及ID_MODEL_ID=?
:ID_VENDOR_ID=?
udevadm info -x /sys/class/block/sdb
sdb
(用适当的块设备名称替换。)
现在,创建一个udev .rules 文件内容如下/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"
在此文件中,使用命令根据上述设备适当替换 ATTRS{idProduct} 和 ATTRS{idVendor} 的整数值udevadm info ...
。
现在,$HOME/.config/systemd/user/
使用以下命令创建目录:
mkdir -p "${HOME}/.config/systemd/user/"
创建一个文件并写入以下内容:${HOME}/.config/systemd/user/[email protected]
[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
创建一个文件并写入以下内容:${HOME}/.config/systemd/user/[email protected]
[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'
现在,使用以下命令创建目录/opt/backup_to_external_disk/bin/
和可执行文件backup_to_external_disk.sh
:
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
现在,将以下内容写入/opt/backup_to_external_disk/bin/backup_to_external_disk.sh
脚本:
#!/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 "GUI mode is active."
_Write_Log "GUI mode is active."
else
__FLAG__GUI_MODE=0
fi
# echo "The block device '${__BLOCK_DEVICE_PATH}' exists. Do you want to mount it and perform a backup? (Y/N)"
zenity --question --title="The block device '${__BLOCK_DEVICE_PATH}' exists." --text="Do you want to mount it and perform a backup from '${HOME}/Documents/' to 'backups/Documents' directory in the external disk?"
declare -i __ZENITY_REPLY_INT=${?}
if [[ ${__ZENITY_REPLY_INT} -ne 0 ]] ; then
_Write_Log "You chose not to backup the device. Will exit now."
exit 1
fi
_Write_Log "You chose to backup the device. Will backup now."
declare __BLOCK_DEVICE_PARTITION_PATH="${__BLOCK_DEVICE_PATH}1"
declare __MOUNT_POINT=""
__MOUNT_POINT="$( udisksctl mount -b "${__BLOCK_DEVICE_PARTITION_PATH}" )"
declare -i __RETURN_STATUS=${?}
## We need to obtain mount point as:
__MOUNT_POINT="${__MOUNT_POINT#Mounted ${__BLOCK_DEVICE_PARTITION_PATH} at }"
if [[ ${__RETURN_STATUS} -eq 0 ]] ; then
_Write_Log "Successfully mounted ${__BLOCK_DEVICE_PARTITION_PATH} at ${__MOUNT_POINT} ."
else
_Write_Log "Failed to mount ${__BLOCK_DEVICE_PARTITION_PATH} ."
exit 1
fi
declare __BACKUP_DESTINATION="${__MOUNT_POINT}/backups/Documents"
if [[ ! -d "${__BACKUP_DESTINATION}" ]] ; then
if ! mkdir -p "${__BACKUP_DESTINATION}" ; then
_Write_Log "Could not create backup destination '${__BACKUP_DESTINATION}' directory."
exit 1
fi
else
_Write_Log "Backup destination '${__BACKUP_DESTINATION}' exists."
fi
_Write_Log "Using backup command: rsync -a '${HOME}/Documents/' '${__BACKUP_DESTINATION}'"
if [[ -d "${__BACKUP_DESTINATION}" ]] ; then
rsync -a "${HOME}/Documents/" "${__BACKUP_DESTINATION}" | zenity --progress --pulsate --auto-close --title="DO NOT EJECT DEVICE ${__BLOCK_DEVICE_PARTITION_PATH}." --text="Backup is in progress..."
_Write_Log "Backup with rsync completed with status=${PIPESTATUS[0]}."
zenity --question --title "Backup Done :: Unmount Device?" --text="The backup operation using rsync command completed with status=${PIPESTATUS[0]}. Do you want to unmount the device?"
__RETURN_STATUS=${?}
if [[ ${__RETURN_STATUS} -eq 0 ]] ; then
udisksctl unmount -b "${__BLOCK_DEVICE_PARTITION_PATH}"
__RETURN_STATUS=${?}
if [[ ${__RETURN_STATUS} -ne 0 ]] ; then
_Write_Log "Unmounting the device ${__BLOCK_DEVICE_PARTITION_PATH} failed."
zenity --warning --title "Unmount failed!" --text="The udisksctl unmount -b ${__BLOCK_DEVICE_PARTITION_PATH} command failed."
else
_Write_Log "Unmounted the device ${__BLOCK_DEVICE_PARTITION_PATH} successfully."
zenity --info --title "Unmount done." --text="The udisksctl unmount -b ${__BLOCK_DEVICE_PARTITION_PATH} command completed successfully."
fi
fi
else
_Write_Log "The backup destination '${__BACKUP_DESTINATION}' does not exist."
exit 1
fi
;;
esac
exit 0
## End of the script.
现在,重新启动系统或运行以下命令:
systemctl --user daemon-reload ; sudo systemctl reload udev
现在,每次将配置的设备连接到系统时,系统都会提示您进行备份。