【问题标题】:Compare checksum of files between two servers and report mismatch比较两台服务器之间的文件校验和并报告不匹配
【发布时间】:2018-10-08 19:10:24
【问题描述】:

我必须将machineA/primary/secondary 文件夹中所有文件的校验和与远程服务器machineB 中此文件夹/bat/snap/ 中的文件进行比较。远程服务器将有很多文件以及我们在machineA 中的文件。

  • 如果校验和有任何不匹配,那么我想用完整路径报告machineA 中存在问题的所有文件,并以非零状态码退出。
  • 如果一切都匹配,则退出零。

我写了一个在machineA 上运行的命令(不确定是否有更好的编写方法),但它非常慢。有什么办法让它更快?

(cd /primary && find . -type f -exec md5sum {} +; cd /secondary && find . -type f -exec md5sum {} +) | ssh machineB '(cd /bat/snap/ && md5sum -c)'

它还会打印出像 ./abc_monthly_1536_proc_7.data: OK 这样的文件名。有什么方法可以在machineA上打印出该文件的完整路径名?

ssh 到每个文件的远程主机肯定不是很有效。 parallel 可以通过同时处理更多文件来加速它,但更有效的方法可能是稍微调整命令,使其通过 ssh 连接到 machineB 并一次性获取所有 md5sum。这可以吗?

【问题讨论】:

  • 要输出绝对路径,只需给它当前的工作目录:find $(pwd) -type f...
  • 我应该在我的命令中添加这个?
  • 而不是cd /primary && find . ...,只需使用find /full/path/primary.,只要您传递绝对路径,find 并不关心您的当前目录是什么。
  • 我明白你的意思。现在明白了。另外我怎样才能使这个命令快速?有没有办法做到这一点?或者有什么更好的写法?
  • 如果/primary/secondary 位于不同的物理磁盘上,您可以通过将cd /secondary 之前的; 更改为& 来稍微加快速度。否则,您已经以非常接近 AFAICT 的最大速度运行。

标签: linux bash shell checksum md5sum


【解决方案1】:

如果您的主要目标不是计算校验和而是列出差异,也许更快(更简单)的方法是运行 rsync--dry-run 选项。如果列出任何文件,它们会有所不同,例如:

MBP:~ jhartman$ rsync -avr --dry-run rsync-test 192.168.1.100:/tmp/; echo $?
building file list ... done
rsync-test/file1.txt

sent 172 bytes  received 26 bytes  396.00 bytes/sec
total size is 90  speedup is 0.45

当然,因为--dry-run 目标上没有文件更改。

希望对你有帮助 贾雷克

【讨论】:

    【解决方案2】:

    如果文件目录/primary/secondary而不是这些目录下,丢失查找。您可能还希望并行化md5-计算。这样就可以了:

    #!/bin/bash
    cd /primary
    md5sum * > /tmp/file-p &
    cd /secondary
    md5sum * > /tmp/file-s &
    wait
    cat  /tmp/file-p /tmp/file-s | ssh machineB '(cd /bat/snap/ && md5sum -c)'
    

    使用相对较少的文件集:

    $ time find . -exec md5sum {} \;
    7e74a9f865a91c5b56b5cab9709f1f36  ./file
    631f01c98ff2016971fb1ea22be3c2cf  ./hosts
    d41d8cd98f00b204e9800998ecf8427e  ./fortune8547
    49d05af711e2d473f12375d720fb0a92  ./vboxdrv-Module.symvers
    bf4b1d740f7151dea0f42f5e9e2b0c34  ./tmpavG1pB
    a9b0d3af1b80a46b92dfe1ce56b2e85c  ./in.clean.4524
    
    real    0m0.046s
    user    0m0.035s
    sys 0m0.006s
    $ time md5sum *
    7e74a9f865a91c5b56b5cab9709f1f36  file
    d41d8cd98f00b204e9800998ecf8427e  fortune8547
    631f01c98ff2016971fb1ea22be3c2cf  hosts
    a9b0d3af1b80a46b92dfe1ce56b2e85c  in.clean.4524
    bf4b1d740f7151dea0f42f5e9e2b0c34  tmpavG1pB
    49d05af711e2d473f12375d720fb0a92  vboxdrv-Module.symvers
    
    real    0m0.005s
    user    0m0.003s
    sys 0m0.002s
    

    (只是为了证明 find 并不总是最快的)。

    【讨论】:

    • 嗯,它看起来确实像find 增加了一点。如果需要递归,我们仍然可以通过 shopt -s globstar 然后 md5sum /primary/**/*find 排除在外。
    【解决方案3】:

    使用md5sum,您可以要求它根据输入md5sum 文件检查文件。

    man md5sum以下两个选项很有用:

    • -c, --check:从文件中读取 MD5 和并检查它们
    • --quiet : 不要为每个成功验证的文件打印 OK

    所以我们需要做的就是构建这样一个文件并传递它。最简单的是以下(来自machineA):

    $ cd /primary; md5sum * | ssh machineB '(cd /bat/snap; md5sum -c - --quiet 2>/dev/null)`
    $ cd /secondary; md5sum * | ssh machineB '(cd /bat/snap; md5sum -c - --quiet 2>/dev/null)`
    

    这会将事情报告为:

    file1: FAILED
    file2: FAILED open or read
    

    这将为您提供每个目录的所有失败文件。您可以稍后使用awk 的任何风格进行任何后期处理。

    【讨论】:

      【解决方案4】:

      您可以尝试并行化另一个答案中提到的过程。将 + 更改为 \;,用 & 执行 bash。

      find $(pwd) -type f -exec bash -c "md5sum '{}' &" \; 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-28
        • 1970-01-01
        • 2012-09-05
        • 1970-01-01
        • 2011-09-29
        • 1970-01-01
        相关资源
        最近更新 更多