如何同步两个目录?

如何同步两个目录?

我想使用 crontab 同步我的 Linux 分区和 Windows 分区之间的两个目录,如下所示:

24 9 * * * cp -r /home/fan/Data /media/T/Data

但它会在原始 Data 目录中创建一个名为 Data 的目录,而不是从源目录复制丢失的文件。我在 cp 手册中找不到合适的选项来完美解决这个问题。我如何将丢失的文件(它们确实存在于目标目录中)从 src 复制到 dir。

顺便说一句,似乎需要挂载T盘才能运行复制命令,当我需要运行命令时如何自动挂载磁盘(挂载命令应以root身份运行)。

如果命令出现异常,我如何获取错误消息?

答案1

用于同步数据的转到工具是rsync。您可以在目录级别同步或仅同步目录的内容,如下所示:

例子

目录同步
24 9 * * * rsync -a /home/fan/Data /media/T/
内容同步
24 9 * * * rsync -a /home/fan/Data/ /media/T/Data/

第一个示例将目录Data从同步/home/fan到目录/media/T。第二个示例将 的内容同步Data到目录/media/T/Data

作为附加提示,我将使用以下表示法同步到目标目录:

24 9 * * * rsync -a /home/fan/Data/ /media/T/Data/.

/.在阅读我的rsync命令时,我发现更加明显。

行为示例

使用rsync可能是我在培训新用户时遇到的最困惑的问题之一。

样本数据:

$ tree home/fan/Data/
home/fan/Data/
|-- file1
|-- file2
|-- file3
|-- file4
`-- file5
1.同步dir Data的内容
$ rsync -a home/fan/Data/ media/T/

请注意,我们将 的内容放入DataT

$ tree media/T/
media/T/
|-- file1
|-- file2
|-- file3
|-- file4
`-- file5

0 directories, 5 files
2.同步目录
$ rsync -a home/fan/Data media/T/

请注意,我们将目录Data放入T.

$ tree media/T/
media/T/
`-- Data
    |-- file1
    |-- file2
    |-- file3
    |-- file4
    `-- file5

1 directory, 5 files

答案2

使用rsync

24 9 * * * rsync -a /home/fan/Data/ /media/T/Data

/在源目录名称末尾添加额外内容将告诉rsync您复制内容而不是完整目录。rsync还将避免复制具有相同时间戳/大小的文件(即在 99.99% 的情况下不需要复制的文件)。

如果您要在同一系统上同步文件,还可以考虑使用--inplace选项来rsync加快速度。从手册页:

--inplace
    This option changes how rsync transfers a file when its data needs to be
    updated: instead of the default method of creating a new copy of the file and
    moving it into place when it is complete, rsync instead writes the updated
    data directly to the destination file.

不过,此选项有利有弊,最大的缺点可能是,如果同步中断,目标文件将处于不一致的状态,只能通过重新开始来修复。

答案3

要解决问题的错误消息部分,您可以选择从 cron 而不是系统命令运行脚本。

24 9 * * * /usr/local/sbin/sync_data.sh

创建文件为/usr/local/sbin/sync_data.sh,授予 root 所有权和执行权限:chown root:root /usr/local/sbin/sync_data.sh && chmod 0700 /usr/local/sbin/sync_data.sh。脚本的内容如下。

#!/usr/bin/env bash
if [[ $EUID -ne 0 ]]; then
    echo "This script must be run as root." 1>&2
    exit 1
fi

# [ ] vs [[ ]] : http://mywiki.wooledge.org/BashFAQ/031

dir_src="/home/fan/Data/"
dir_dst="/media/T/"

# A Boolean to know if running interactively or not
b_interactive=1
if [[ -v PS1 ]] ; then # The "-v PS1" method is for BASH 4.2+
    $b_interactive=0   # Could also use [[ -z "$PS1" ]]
fi

# Send messages to console or syslog.
function notify() {
    message="$1"
    if [[ $b_interactive -eq 1 ]] ; then
        echo "$message"
    else
        # eval combines args into a single string for execution...
        eval $cmd_logger -p err "$0: $message"
    fi
}

# If the mount point if not currently mounted...
if [[ "$(grep $dir_dst /proc/mounts)" = "" ]] ; then
    # Try to mount the directory.
    mount $dir_dst

    # Send a message to console or syslog.
    if [[ $? -ne 0 ]] ; then
        notify("$0 failed to mount $dir_dst")
        exit 1;
    fi
fi

# Create a backup directory if it does not exist
if [[ -d $dir_dst ]] ; then
    mkdir -p $dir_dst 2>/dev/null
fi

# A one-way sync to dir_dst, deleting files that no longer exist in DIR_SRC...
rsync -a --delete $dir_src $dir_dst &> /dev/null

# Check the return status of last command...
if [ $? -eq 0 ]; then
    notify("$0: the rsync process succeeded.");
else
    notify("$0: the rsync process failed.");
fi

unset dir_src
unset dir_dst
unset b_interactive

答案4

mkdir /office
mount /dev/xvdf /office
mkdir /home
mount /dev/xvdf1 /home

rsync -aHAXxSP /office /home

相关内容