2013-03-08 199 views
1

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

我正在使用Solaris Unix。

+2

保存旧的文件大小,然后使用'tail -c + $ filesize logfile'。 – Barmar 2013-03-08 20:26:27

+0

为什么“cron”使事情变得复杂?启动一个进程并将其读到文件末尾,然后休眠一段时间(保持文件打开)。当它醒来时,从它进入睡眠状态时的文件位置读取更多数据。 – 2013-03-08 20:56:52

+0

或管'tail -f',它可以自动执行“读取,休眠”循环。 – Barmar 2013-03-08 21:02:12

回答

0

已经指出的最好的方法是使用“tail -f”,但假设由于某种原因你的程序死了,你将不得不从头开始阅读,并且你不能使用“tail -f”继续它离开的地方。

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

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

如果数据文件被某些其他应用程序截断,则还应该获取该应用程序以删除控制文件。否则,你将不得不寻找一些其他方式知道该文件是新的。它可能是你读的“fseek”比当前的“ftell”更大,这表明文件比它小,但这不会涵盖所有可能性。

你可以调查“FSTAT”,并使用数据文件的创建时间,看它是否比你会保存在控制文件OR,如果你能创建时间较新的,我会写一个日期/时间戳记在文件的第一行,并将其写入控制文件中。当应用程序重新启动时,如果第一行时间戳与控制文件时间戳不匹配,则从头开始读取。否则,“fseek”会将您带到正确的位置。

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 

所以主要的工具有“尾巴”。询问我是否有任何问题。

+0

'tail -n'需要从头开始读取文件;由于文件很大,这可能相当耗时。因此,'tail -c'(正如Barmar上面所建议的)可能会更好。 – Armali 2014-06-05 06:36:04