AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 461283
Accepted
ynn
ynn
Asked: 2018-08-09 04:58:16 +0800 CST2018-08-09 04:58:16 +0800 CST 2018-08-09 04:58:16 +0800 CST

为什么使用`rsync`命令时`--modify-window=1`?

  • 772

据微软称,

当文件从 NTFS 驱动器复制到 FAT 驱动器时,必须进行一些文件时间戳舍入;文件时间戳向上舍入到下一个偶数秒。

(剪断)

NTFS 时间戳:7 小时 31 分 0 秒 001。

FAT 时间戳变为 7 小时 31 分 2 秒 000。

然而,man rsync说

--修改窗口

当比较两个时间戳时,如果它们的差异不超过 modify-window 值,rsync 会将它们视为相等。这通常为 0(对于精确匹配),但您可能会发现在某些情况下将其设置为更大的值很有用。特别是,在与 MS Windows FAT 文件系统(以 2 秒分辨率表示时间)之间进行传输时, --modify-window=1 很有用(允许时间最多相差 1 秒)。

我认为--modify-window=2是正确的选择,因为没有执行“四舍五入”,而是完成了“天花板”。谁能告诉我我是否正确?


相关或无关信息:

在我的环境中,FAT32 USB中文件的mtime分辨率为1秒,“地板”完成,但我不知道原因。USB 使用fdisk和格式化mkfs -t fat -F 32。文件从 Linux Mint 传输到 Volumio。我检查时间戳,使用date -r +%s.%N.


补充:

我找到了另一个信息。一个可靠的 rsync 邮件线程说

时间戳将始终是 vfat 上的一个问题。它具有 1 或 2 秒的分辨率,因此 --modify-window=2 是一种常见的解决方案。

但这与man rsyncStackExchange 上推荐的许多公认答案相矛盾--modify-window=1。现在我很困惑。

rsync
  • 2 2 个回答
  • 6802 Views

2 个回答

  • Voted
  1. Best Answer
    frostschutz
    2018-08-11T10:43:12+08:002018-08-11T10:43:12+08:00

    只是为了避免对 modify_window 的工作方式产生任何混淆,它在任一方向上都进行了检查。(如果您想在源代码中阅读此内容,请检查 util.c :: cmp_time()。)

    这意味着,

    • 如果 A 比 B 新,它会检查 A 是否仍然比 B + modify_window 更新。
    • 如果 B 比 A 更新,它会检查 B 是否仍然比 A + modify_window 更新。

    因此,假设原始 A 的时间为 123,但您的备份文件系统很糟糕,因此副本 B 以时间 122(使 A 比 B 更新)或时间 124(使 B 比 A 更新)结束。

    modify_window = 1 会发生什么?

    • 如果 A (123) 比 B (122) 更新,它检查 A (123) 是否仍然比 B (122+1 = 123) 更新。
    • 如果 B (124) 比 A (123) 更新,它检查 B (124) 是否仍然比 A (123+1 = 124) 更新。

    在这两种情况下,结果是相同的,因此 modify_window = 1 足以让时间在任一方向上偏离一秒。

    根据 rsync 手册页,这对于 FAT32 来说应该足够好(tm)。

    根据您引用的文档(将 122 变成 124,这到底是怎么回事),这还不够好。

    所以这是不确定的。


    通过实验,在 Linux 中使用 NTFS(-3g) 和 FAT32, modify_window = 1 似乎工作正常。

    因此,我的测试设置是:

    truncate -s 100M ntfs.img fat32.img
    mkfs.ntfs -F ntfs.img
    mkfs.vfat -F 32 fat32.img
    mount -o loop ntfs.img /tmp/ntfs/
    mount -o loop fat32.img /tmp/fat32/
    

    所以,一个 100M NTFS/FAT32 文件系统。

    创建一千个具有各种时间戳的文件:

    cd /tmp/ntfs
    
    for f in {000..999}
    do
        sleep 0.0$RANDOM # widens the timestamp range
        touch "$f"
    done
    

    例如:

    # stat --format=%n:%y 111 222 333
    111:2018-08-10 20:19:10.011984300 +0200
    222:2018-08-10 20:19:13.553878700 +0200
    333:2018-08-10 20:19:17.765753000 +0200
    

    根据你的说法,20:19:10.011应该是2018-08-10 20:19:12.000.

    那么让我们看看会发生什么。首先,将所有这些文件复制到 FAT32。

    # rsync -a /tmp/ntfs/ /tmp/fat32/
    

    然后我注意到时间戳实际上是准确的,直到您卸载并重新安装:

    # umount /tmp/fat32
    # mount -o loop fat32.img /tmp/fat32
    

    相比:

    # stat --format=%n:%y /tmp/{ntfs,fat32}/{111,222,333}
    /tmp/ntfs/  111:2018-08-10 20:19:10.011984300 +0200
    /tmp/fat32/ 111:2018-08-10 20:19:10.000000000 +0200
    /tmp/ntfs/  222:2018-08-10 20:19:13.553878700 +0200
    /tmp/fat32/ 222:2018-08-10 20:19:12.000000000 +0200
    /tmp/ntfs/  333:2018-08-10 20:19:17.765753000 +0200
    /tmp/fat32/ 333:2018-08-10 20:19:16.000000000 +0200
    

    所以这看起来很像我。我不知道 Windows 是否会这样做,但这是使用 Linux 和 rsync 会发生的情况。

    再次复制时 rsync 会做什么:

    # rsync -av --dry-run /tmp/ntfs/ /tmp/fat32
    sending incremental file list
    ./
    000
    001
    002
    035
    036
    ...
    963
    964
    997
    998
    999
    

    所以列表中有一些空白,但总的来说,它会重新复制很多文件。

    使用--modify-window=1,列表为空:

    # rsync -av --dry-run --modify-window=1 /tmp/ntfs/ /tmp/fat32/
    sending incremental file list
    ./
    

    因此,至少对于 Linux,手册页是准确的。偏移量似乎永远不会大于 1。(嗯,一个加分数,但这也被忽略了。)


    那么,你应该使用--modify-time=2吗?直到您可以通过实验证明这实际上是一种可能的情况。即使那样,也很难说。这首先是一个可怕的黑客攻击,时间窗口越大,就越有可能错过真正的修改。

    甚至--modify-time=1已经忽略了与 FAT32 时间戳四舍五入的方式无关的更改 - 因为它是双向的,但 FAT32 只会楼层,并且 rsync 在复制到 FAT32 时会忽略这一点(目标文件只能更旧),反之亦然从 FAT32 复制时反之亦然(目标文件只能更新)。

    似乎不存在更好地处理此问题的选项。


    我还尝试在内核源代码中追踪这种行为,不幸的是,注释(在 linux/fs/fat/misc.c 中)并没有给出太多的信息。

    /*
     * The epoch of FAT timestamp is 1980.
     *     :  bits :     value
     * date:  0 -  4: day   (1 -  31)
     * date:  5 -  8: month (1 -  12)
     * date:  9 - 15: year  (0 - 127) from 1980
     * time:  0 -  4: sec   (0 -  29) 2sec counts
     * time:  5 - 10: min   (0 -  59)
     * time: 11 - 15: hour  (0 -  23)
     */
    

    所以根据这个,FAT时间戳使用5位秒,所以你只得到32个可能的状态,其中30个被使用。转换是通过一个简单的位移来完成的。

    在 fs/fat/misc.c :: fat_time_unix2fat()

        /* 0~59 -> 0~29(2sec counts) */
        tm.tm_sec >>= 1;
    

    所以 0 是 0,1 是 0,2 是 1,3 是 1,4 是 2,依此类推......

    在 fs/fat/misc.c :: fat_time_fat2unix()

        second =  (time & 0x1f) << 1;
    

    与上述0x1f相反,是位掩码,仅抓取 FAT 时间的位 0-4,表示 0-29 秒。

    如果这与应有的不同,那么我可以看到的评论中没有任何内容。


    Raymond Chen 发表的一篇有趣的文章,讲述了为什么 Windows 会费尽心机地赶时间:https ://blogs.msdn.microsoft.com/oldnewthing/20140903-00/?p=83

    好的,但是为什么时间戳总是增加到最接近的两秒间隔?为什么不四舍五入到最接近的两秒间隔?这样,时间戳更改最多为一秒。

    因为四舍五入到最接近的间隔意味着文件可能会在时间上倒退,这会产生自己的问题。(因果关系可能会如此拖累。)

    据此,Windowsxcopy工具有一个/D标志,上面写着“如果比目标文件更新,则只复制源文件”。基本上是什么rsync --update或cp --update会做什么。

    将时间缩短,使文件似乎是在过去 1 秒创建的,就像在 Linux 中发生的那样,会导致每次运行命令时都重新复制文件。四舍五入时间解决了这个问题。

    OTOH Windows 解决方案在复制这些文件时同样让您头疼。它会复制比实际更新的文件,然后您必须小心汇总不会发生两次。

    不管你做什么,它总是错的,一个不能正确存储时间戳的文件系统只是一个麻烦。

    • 11
  2. Dieter Hug
    2020-01-07T13:05:31+08:002020-01-07T13:05:31+08:00

    上面的所有数学证明,如果你的 fat32 分区四舍五入/截断/截断到 1 秒,--modify-window=1就是正确的答案。尽管如此:在我的 fat32 分区上,我找不到任何奇数秒的文件......:

    ls -Rla --time-style=full-iso | grep '[13579]\.000000000 ' | wc -l
    

    尽管:

    ls -Rla --time-style=full-iso | grep '[02468]\.000000000 ' | wc -l
    

    表明那里有很多文件。

    我坚持:--modify-window=2

    • 2

相关问题

  • rsync - 使用 shell 脚本将每个 JPG/jpg 文件从一个硬盘驱动器移动到一个目录

  • tar 目录只发送修改过的文件块

  • 如何复制具有相对重复符号链接的目录树?

  • rsync 排除问题

  • rsync 端口 22 和 873 使用

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    ssh 无法协商:“找不到匹配的密码”,正在拒绝 cbc

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    如何卸载内核模块“nvidia-drm”?

    • 13 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add 返回:“连接代理时出错:没有这样的文件或目录” 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve