我有几个日志文件,每次增加一行,就像日志文件一样。这些文件可通过 SMB 网络共享获取。
我想要定期复制这些文件。由于网络速度较慢且拥塞,我不想每次都传输整个文件,而只想传输上次复制后添加的新行。
我可以相信生成日志的程序只会将内容附加到文件末尾。(如果日志文件的某些部分在写入后以某种方式被修改,那么整个日志将变得不可信且无用)。不需要比较源文件和目标文件的开头。
源文件和目标文件夹仅可通过 SMB 文件共享访问,两个系统之间不允许使用其他通信渠道。
运行复制任务的 PC 可以访问源文件共享和目标文件共享,但两个共享位于不同的网络中,并且这台 PC 是它们之间的唯一桥梁。
有没有巧妙地结合使用 robocopy、xcopy 或其他 Windows 命令来实现此目的?Robocopy 可以恢复部分下载,但在这种情况下我无法让它工作。
我读到过 RSync 服务器在这里会有所帮助,但是通信必须跨越多个企业防火墙,阻止除 smb 文件共享之外的所有内容,并且生成日志的设备不应被修改,所以我不认为这是一个选择。
答案1
Windows 10 和 Windows Server 2019 附带:
curl.exe file:////thedevice/sharename/input.log -o \\target\logs\output.log -C -
选项-C
在指定字节位置恢复传输。请注意,它不跳过不需要的数据 – 它力求所需的起始位置,这样前面的数据就永远不会被读取。对于 HTTP,这意味着使用 Range 请求;对于直接文件系统访问,它实际上意味着 seek() 操作。
任何其他实现直接文件操作的工具也可以工作,例如使用 PowerShell [System.IO.File]::Open()
,或者 Python(如果您可以在中间机器上安装它)(这仅用于演示目的):
source = r"\\thedevice\sharename\input.log"
target = r"\\target\logs\output.log"
with open(source, "rb") as srcf:
with open(target, "ab") as dstf:
last_pos = dstf.tell()
print("Restarting at byte", last_pos)
srcf.seek(last_pos)
while buf := srcf.read(1*1024*1024):
dstf.write(buf)
print("Copied", srcf.tell() - last_pos, "bytes")
答案2
可以比较新旧日志并仅复制新行,但这有点弄巧成拙。
比较操作本身需要读取网络文件,这完全等同于复制它。您不会获得任何性能提升。
您也许可以设置远程计算机的参数,使其频繁启动新的日志文件,或者仅在非拥塞时复制文件,或者甚至在传输之前在远程计算机上压缩文件以减少文件大小。这个问题的解决方案并不多。
答案3
目标日志文件包含从源日志复制的最新详细信息。从目标日志中获取行计数值,然后在从源日志读取时使用该数字跳过该行数。将该行之后的内容附加到目标日志文件。
下面的 PowerShell 示例使用获取内容通过管道传输到选择对象使用-skip
基于复制日志当前行数的数值参数,然后将其通过管道传输到添加内容按需要附加新的日志文件数据。
电源外壳
$targetFile = "\\tserver\tshare\tfolder\CopyLog.txt";
$sourceFile = "\\sserver\sshare\sfolder\xyz.txt";
$tFLC = (Get-Content $targetFile).Count;
(Get-Content $sourceFile | Select-Object -Skip $tFLC) | Add-Content $targetFile;