0

我正在尝试编写一个(sh -bourne shell)脚本,在将行写入文件时对其进行处理。我试图通过将输出tail -f输入while read循环来做到这一点。根据我在 Google 的研究以及处理类似问题但使用 bash 的这个问题,这种策略似乎是正确的。

从我读过的内容来看,当被跟踪的文件不再存在时,我似乎应该能够跳出循环。它没有。实际上,似乎我可以摆脱这种情况的唯一方法是在另一个会话中终止该进程。tail似乎确实可以正常工作,否则作为测试:

触摸文件
尾 -f 文件 | 而读线
做
  回声$线
完毕

我在另一个会话中附加的数据file只是来自上面编写的循环处理的文件。

这是在 HP-UX 版本 B.11.23 上。

感谢您提供的任何帮助/见解!

4

5 回答 5

1

If you want to break out, when your file does not exist any more, just do it:

 test -f file || break

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:

  tail -f test.file | while read -t 3 line || test -f test.file; do 
          some stuff with $line
  done
于 2008-12-04T06:10:42.283 回答
0

除非您使用 GNU tail,否则它不会在跟随文件时自行终止。-f 选项实际上只用于交互式监控——事实上,我有一本书说 -f “不太可能在 shell 脚本中使用”。

但是对于问题的解决方案,我不完全确定这不是一种过度设计的方法,但我认为你可以将尾部发送到 FIFO,然后有一个函数或脚本来检查文件如果它没有链接,存在并杀死尾巴。

#!/bin/sh

哨兵()
{
    虽然是真的
    做
        如果 [ !-e $1]
        然后
            杀死 2 美元
            rm /tmp/$1
            休息
        菲
    完毕
}       

触摸 $1

mkfifo /tmp/$1

尾 -f $1 >/tmp/$1 &

哨兵$ 1 $!&

猫 /tmp/$1 | 而读线
做
    回声$线
完毕

做了一些幼稚的测试,它似乎工作正常,并且没有留下任何垃圾。

于 2008-12-10T01:51:48.900 回答
0

我不了解 HP-UX tail,但 GNUtail可以--follow=name选择按名称跟随文件(每隔几秒钟重新打开文件,而不是从不会检测文件是否未链接的相同文件描述符中读取)和当用于打开文件的文件名被取消链接时将退出:

tail --follow=name test.txt
于 2008-12-04T04:33:09.347 回答
0

我从来没有对这个答案感到满意,但我也没有找到替代方案:

kill $(ps -o pid,cmd --no-headers --ppid $$ | grep tail | awk '{print $1}')

获取当前进程的所有子进程,查找尾部,打印出第一列(尾部的 pid),然后将其杀死。确实丑陋的罪恶,这就是生活。

于 2009-02-27T22:39:38.263 回答
0

以下方法将tail -f file命令设置为背景,将其进程 ID 和自定义字符串前缀(此处 tailpid: )回显到while循环中,其中带有自定义字符串前缀的行触发另一个(背景)while循环,该循环每 5 秒检查一次是否file仍然存在。如果不是,tail -f file则被杀死并且包含后台while循环的子shell 退出。

# cf. "The Heirloom Bourne Shell",
# http://heirloom.sourceforge.net/sh.html,
# http://sourceforge.net/projects/heirloom/files/heirloom-sh/ and
# http://freecode.com/projects/bournesh

/usr/local/bin/bournesh -c '
touch file
(tail -f file & echo "tailpid: ${!}" ) | while IFS="" read -r line
do
   case "$line" in
      tailpid:*) while sleep 5; do 
                       #echo hello; 
                       if [ ! -f file ]; then
                          IFS=" "; set -- ${line}
                          kill -HUP "$2"
                          exit
                       fi
                 done & 
                 continue ;;
   esac
   echo "$line"
done
echo exiting ...
'
于 2013-02-23T16:15:59.760 回答