日志文件内容的增量复制

日志文件内容的增量复制

我有几个日志文件,每次增加一行,就像日志文件一样。这些文件可通过 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;

支持资源

  • 获取内容

  • 选择对象

    -Skip

    跳过(不选择)指定数量的项目。默认情况下,Skip 参数从对象数组或列表的开头开始计数,但如果命令使用 Last 参数,则从列表或数组的末尾开始计数。

    与从 0 开始计数的 Index 参数不同,Skip 参数从 1 开始。

  • 添加内容

相关内容