突破“tail -f” 正在由“读取时”读取 HP-UX 中的循环
我正在尝试编写一个(sh -bourne shell)脚本来处理写入文件的行。 我尝试通过将 tail -f
的输出输入到 while read
循环中来实现此目的。 根据我在 Google 的研究以及 这个问题处理类似的问题,但使用的是 bash。
根据我所读到的内容,当所跟踪的文件不再存在时,我似乎应该能够跳出循环。 事实并非如此。 事实上,似乎我能摆脱这种情况的唯一方法是在另一个会话中终止该进程。 tail
似乎工作正常,否则与此测试:
touch file tail -f file | while read line do echo $line done
我在另一个会话中附加到 file
的数据似乎只是上面编写的循环处理中的文件。
这是 HP-UX 版本 B.11.23 上的。
感谢您提供的任何帮助/见解!
I'm trying to write a (sh -bourne shell) script that processes lines as they are written to a file. I'm attempting to do this by feeding the output of tail -f
into a while read
loop. This tactic seems to be proper based on my research in Google as well as this question dealing with a similar issue, but using bash.
From what I've read, it seems that I should be able to break out of the loop when the file being followed ceases to exist. It doesn't. In fact, it seems the only way I can break out of this is to kill the process in another session. tail
does seem to be working fine otherwise as testing with this:
touch file tail -f file | while read line do echo $line done
Data I append to file
in another session appears just file from the loop processing written above.
This is on HP-UX version B.11.23.
Thanks for any help/insight you can provide!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
如果您想突破,当您的文件不再存在时,只需执行以下操作:
将其放入循环中,应该会突破。
剩下的问题是,如何中断读取行,因为这是阻塞的。
您可以通过应用超时来完成此操作,例如 read -t 5 行。 然后每 5 秒读取返回一次,如果文件不再存在,循环就会中断。 注意:创建循环以处理读取超时但文件仍然存在的情况。
编辑:似乎超时读取返回 false,因此您可以将测试与超时结合起来,结果将是:
If you want to break out, when your file does not exist any more, just do it:
Placing this in your loop, should break out.
The remaining problem is, how to break the read line, as this is blocking.
This could you do by applying a timeout, like read -t 5 line. Then every 5 second the read returns, and in case the file does not longer exist, the loop will break. Attention: Create your loop that it can handle the case, that the read times out, but the file is still present.
EDIT: Seems that with timeout read returns false, so you could combine the test with the timeout, the result would be:
我不知道 HP-UX
tail
但 GNUtail
有--follow=name
选项,它将按名称跟随文件(通过每隔几秒重新打开文件而不是从同一文件描述符读取,这将不会检测文件是否已取消链接),并且当用于打开文件的文件名取消链接时将退出:I don't know about HP-UX
tail
but GNUtail
has the--follow=name
option which will follow the file by name (by re-opening the file every few seconds instead of reading from the same file descriptor which will not detect if the file is unlinked) and will exit when the filename used to open the file is unlinked:除非您使用 GNU tail,否则它在跟踪文件时不可能自行终止。 -f 选项实际上仅用于交互式监控——事实上,我有一本书说 -f “不太可能在 shell 脚本中使用”。
但对于问题的解决方案,我不完全确定这不是一种过度设计的方法,但我认为你可以将 tail 发送到 FIFO,然后有一个函数或检查文件是否存在并杀死尾部(如果它已取消链接)的脚本。
做了一些简单的测试,它似乎工作正常,并且没有留下任何垃圾。
Unless you're using GNU tail, there is no way it'll terminate of its own accord when following a file. The -f option is really only meant for interactive monitoring--indeed, I have a book that says that -f "is unlikely to be of use in shell scripts".
But for a solution to the problem, I'm not wholly sure this isn't an over-engineered way to do it, but I figured you could send the tail to a FIFO, then have a function or script that checked the file for existence and killed off the tail if it'd been unlinked.
Did some naïve testing, and it seems to work okay, and not leave any garbage lying around.
我对这个答案一直不满意,但我也没有找到替代方案:
获取当前进程的子进程的所有进程,查找尾部,打印出第一列(尾部的 pid),然后杀死它。 罪孽极其丑陋,这就是生活。
I've never been happy with this answer but I have not found an alternative either:
Get all processes that are children of the current process, look for the tail, print out the first column (tail's pid), and kill it. Sin-freaking-ugly indeed, such is life.
以下方法将
tail -f file
命令设置为后台,将其进程 ID 加上自定义字符串前缀(此处为tailpid:
)回显到while
循环其中带有自定义字符串前缀的行会触发另一个(后台)while
循环,每 5 秒检查一次file
是否仍然存在。 如果不是,tail -f file
会被终止,并且包含后台while
循环的子 shell 会退出。The following approach backgrounds the
tail -f file
command, echos its process id plus a custom string prefix (heretailpid:
) to thewhile
loop where the line with the custom string prefix triggers another (backgrounded)while
loop that every 5 seconds checks iffile
is still existing. If not,tail -f file
gets killed and the subshell containing the backgroundedwhile
loop exits.