【问题标题】:read a file from last position using shell script使用 shell 脚本从最后一个位置读取文件
【发布时间】:2014-06-06 01:09:28
【问题描述】:

我的要求是读取一个使用 cron 作业中的 shell 脚本不断更新的大文件。我会一直读到最后一行,然后停止这个过程。下次 cron 作业开始时,作业应该从上次完成的位置读取。任何建议如何在 shell 脚本中执行此操作。

我正在使用 Solaris Unix。

【问题讨论】:

  • 保存旧文件大小,然后使用tail -c +$filesize logfile
  • 为什么要用cron 使事情复杂化?启动一个进程并让它读到文件的末尾,然后休眠一段时间(保持文件打开)。当它醒来时,从它进入睡眠时所在的文件位置读取更多数据。
  • 或管道tail -f,它会自动执行“读取、睡眠”循环。

标签: shell unix file-io


【解决方案1】:

试试这个(当然是在cron中添加):

#!/bin/bash

#STAT_FILE=/tmp/stat.tmp
PREV_LINE_STAT=/tmp/prev_last_line.tmp
LINE=$(cat log | wc -l)
LOG=/tmp/log.tmp

if [ -f $PREV_LINE_STAT ]
then
    PREV_LINE=$(cat $PREV_LINE_STAT)
else
    PREV_LINE=0
fi

declare -i LINE_RANGE
LINE_RANGE=$LINE-$PREV_LINE


if [ $LINE_RANGE -lt 0 ]
then
    LINE_RANGE=$LINE
fi

tail -n $LINE_RANGE log > $LOG

COUNT1=$(grep any_word $LOG |wc -l)

echo "-------------------
LINE_RANGE is $LINE_RANGE
-------------------
number of words 
$COUNT1" > test.txt

echo $LINE > $PREV_LINE_STAT

cat test.txt

所以这里的主要工具是“尾巴”。有什么问题可以问我。

【讨论】:

  • tail -n 要求从头开始读取文件;由于文件很大,这可能非常耗时。因此,tail -c(正如上面 Barmar 建议的那样)可能会更好。
【解决方案2】:

如前所述,最好的方法是使用“tail -f”,但假设由于某种原因您的程序死了,您将不得不从头开始阅读,并且不能使用“tail -f”继续它停止了。

所以唯一的方法是编写自己的 C 应用程序。它应该很容易,因为它相当简单。您可以使用“ftell”来找出您在数据文件中的位置。然后,您将在退出应用程序之前或在每次读取之后(如果您不再重新处理一行至关重要)将该结果写入其他文件(控制文件)。

重新启动应用程序后,您会读取该控制文件,解析值并使用“fseek”跳转到您离开的地方。

如果数据文件被其他应用程序截断,您还应该让该应用程序删除您的控制文件。否则,您将不得不找到其他方法来知道该文件是新文件。可能是您读取的“fseek”大于当前的“ftell”,这表明文件比原来小,但这并不能涵盖所有可能发生的情况。

您可以调查“fstat”并使用数据文件的创建时间来查看它是否比您保存在控制文件中的创建时间更新或者如果可以的话,我会在文件的第一行写入日期/时间戳,并将其也写入控制文件。当应用重启时,如果第一行时间戳与控制文件时间戳不匹配,则从头开始读取。否则,“fseek”应该会将您带到正确的位置。

【讨论】:

    猜你喜欢
    • 2019-07-26
    • 1970-01-01
    • 2011-08-24
    • 1970-01-01
    • 2012-10-06
    • 2019-02-10
    • 2013-06-07
    • 1970-01-01
    相关资源
    最近更新 更多