![rsync 文件仅 2 小时后未修改?](https://linux22.com/image/181985/rsync%20%E6%96%87%E4%BB%B6%E4%BB%85%202%20%E5%B0%8F%E6%97%B6%E5%90%8E%E6%9C%AA%E4%BF%AE%E6%94%B9%EF%BC%9F.png)
我在远程服务器上有一个应用程序,大约每 2 小时生成新的二进制文件。每 6 分钟,如果有新数据,则更新文件。它们在 19 次追加后关闭,这意味着如果每新 6 分钟之间有新数据,它们将在 1 小时 54 分钟后关闭。
它们是镶木地板文件:
- 可以附加镶木地板文件,直到它们不关闭,这就是我的应用程序所做的。
- parquet 文件在关闭之前无法打开
文件名采用下面的形式。最后一位数字是创建文件时的时间戳。此时间戳随后不会更新。
my-data-1602915797.parquet
my-data-1609890860.parquet
my-other-d-1609990998.parquet
my-other-d-1610000010.parquet
一旦完整的文件被写入,并且一旦它们被安全地复制到本地(在我的 8To 本地硬盘上),我必须从远程删除它们(远程上只有 160Go 硬盘)该应用程序每生成 4 到 5Go 的数据天。
我计划每月启动一次此文件传输。
所以,我只想转移那些已经关闭的。要选择它们,我可以使用 ssh。
# IP address is a dummy address ;)
ssh [email protected] "find /root/my_data -name *.parquet -maxdepth 1 -type f -mmin +180"
然后将其输入到rsync
.
但后来我发现这个线程据说可以使用 来解决
rsync -a
。
查看 rsync 手册页,我无法找出此参数如何满足此需求。请问有谁帮忙理解一下吗?
感谢您的任何反馈,非常感谢。
答案1
您可以rsync
按照所描述的方式复制文件,并在成功复制后将其删除:
rsync --dry-run -avz --remove-source-files [email protected]:'$(find /root/my_data -maxdepth 1 -name "*.parquet" -type f -mmin +30)' /my/destination
请注意,
- 我使用单引号而不是双引号来包围计算的命令,
$( find ... )
以便它在远程服务器而不是本地服务器的上下文中执行 - 我已引用
*.parquet
阻止 shell 尝试将其与您的一个(或多个)镶木地板文件匹配的方法 - 我已将延迟从上次更新后的 180 分钟减少到仅 30 分钟(你说最新文件每六分钟更新一次,所以 30 就足够了)
- 我曾经用来
-z
压缩网络连接上的数据流。即使使用预压缩的数据,这也会有一点帮助 - 该目录
/my/destination
是将 parquet 文件移动到的本地目录
我强烈建议您尝试启用它以--dry-run
检查将要发生的情况,然后在您对预期结果感到满意时删除该参数
--progress
如果您想实时观看每个文件的传输进度,请添加。不要在这里使用-P
或--partial
。
我应该指出,没有简单的方法来识别已“关闭”的文件。您可以编写一些代码来使用lsof
,也可以编写一些来自inotify
家族的代码。我在这里所做的是依靠应用程序在上次更新后的 30 分钟内写入当前文件,以便操作系统可以相应地自动更新文件修改时间。如果您的应用程序摆弄文件修改时间(元数据,而不是文件名),那么这将会中断。
最干净的解决方案是修改您的应用程序以创建其文件,*.parquet.tmp
然后*.parquet
在完成写入后将它们重命名为相应的文件。 (这将允许您保证只有*parquet
文件已完成,因此适合复制。)但我确实意识到这可能是不可能的。
答案2
如果您确实无法复制文件(除非文件已关闭),则可以使用find
生成文件列表。rsync
您也可以直接使用rsync
。它会复制打开的部分文件,但这为什么重要。它们更改后,rsync
会注意到它们已更新并同步它们。
答案3
探索使用lsof
@Lucas 的建议,我想出了这两行。
将命令的输出格式化lsof
为干净的文件名列表变得相当复杂,但这种方式可以确保只保留关闭的文件,无论生成文件的应用程序中可能有什么更改。
ssh root@"$RMT_IP" "lsof +D "$RMT_PATH_DATA" | tr -s ' ' | cut -d' ' -f9 | tail -n +2 | grep '.parquet$' | xargs -n 1 basename" > "$OPEN_FILES"
rsync --dry-run -avv --remove-source-files --exclude-from="$OPEN_FILES" root@"$RMT_IP":"$RMT_PATH_DATA"/*.txt "$TEMP_LOC_PATH"
-vv 参数生成rsync
跳过的详细文件。在我的测试文件中,我可以检查列表$OPEN_FILES
是否正确读取。