我怎么告诉尾巴-f它已经完成 - 干净利落?

时间:2014-11-18 00:42:07

标签: bash unix cygwin gzip tail

我正在创建一个LOGFILE到远程服务器。

tail -f LOGILE | gzip -c >> /faraway/log.gz

然而,当原始LOGFILE关闭并移动到存储目录时,我的tail -f似乎得到了一些奇怪的数据。

如何确保tail -f干净地停止并且压缩文件/faraway/log.gz是LOGFILE的真实副本?

编辑1

我做了一些挖掘。

/faraway/log.gz严重终止 - 在FIX消息的中途。这一定是因为我控制了上面的整个管道命令。

如果忽略最后一行,则原始LOGFILE和log.gz完全匹配!对于在大西洋上空传输的40G文件而言。

我印象非常深刻,因为它完全符合我的要求。有没有读者认为我只是"幸运"在这种情况下 - 这可能不会在将来发挥作用吗?

现在,我只需要清理一下gzip。也许如下所示向尾部PID发送kill -9可能允许GZIP正确完成其压缩。

2 个答案:

答案 0 :(得分:0)

要获得完整副本,请使用

tail -n +1 -f your file

如果您不使用-n +1选项,则只能获得文件的尾部。

然而,这并没有解决删除/移动文件问题。事实上,删除/移动文件问题是IPC(进程间通信)问题,或进程间协作问题。如果您没有其他流程的正确行为模型,则无法解决问题。

例如,如果其他程序将日志文件复制到其他地方,然后删除当前文件,然后程序将输出记录到该新日志文件中...显然你的尾部无法读取这些输出。

unix(和unix-like system)的相关功能值得一提:

  

打开文件以供进程A读取,但随后将其删除   进程B,物理内容不会立即删除,   因为它的引用计数不为零(有人仍在使用它,即   过程A)。进程A仍然可以访问该文件,直到它关闭   文件。移动文件是另一个问题:如果进程B,请移动   文件到同一物理文件系统(注意:你可能有很多   物理文件系统附加在您的系统上),进程A仍然可以   访问文件,甚至文件也在增长。这种感动是   只是为了更改名称(路径名+文件名),仅此而已。该   文件的标识(a.k.a。" i-node"在unix中)不会改变。然而   如果文件被移动到另一个物理文件系统,本地或远程,   就像文件被复制然后被删除一样。所以删除规则   提到的可以适用。

您提到的缺失行问题很有意思,可能需要对生成和移动/删除日志文件的程序/进程的行为进行更多分析。

<强> - 更新 -

很高兴看到你取得了一些进展。就像我说的那样,tail之类的进程仍然可以访问数据 在类似unix的系统中删除该文件。

你可以使用       (echo $ BASHPID&gt; / tmp / PID_tail; exec tail -n + 1 -f yourLogFile)| gzip -c - &gt; yourZipFile.gz

gzip你的日志文件,并通过

杀死tail程序
kill -TERM `cat /tmp/PID_tail`

gzip应该自行完成而不会出错。即使您担心gzip会受到损害 管道信号,您可以使用这种替代方法来防止管道损坏:

 (  ( echo $BASHPID > /tmp/PID_tail; exec tail -n + 1 -f yourLogFile ) ; true ) | gzip -c - > yourZipFile.gz

破损的管道受true保护,{{1}}不会打印任何内容,但会自行结束。

答案 1 :(得分:0)

来自tail manpage强调我的

<块引用>

使用--follow(-f),tail默认跟随文件 描述符,这意味着即使尾文件被重命名, tail 将继续跟踪它的结束。此默认行为是 当您真的想跟踪的实际名称时,这是不可取的 文件,而不是文件描述符(例如,日志轮换)。 使用 --follow=name 在这种情况下。这会导致尾部跟踪命名 文件以适应重命名、删除和创建的方式。

因此您提出的问题的解决方案是使用:

tail --follow=name LOGILE | gzip -c >> /faraway/log.gz

这样,当文件被删除时,tail 会停止读取它。