簡體   English   中英

使用copytruncate時如何在perl中尾文件

[英]How to tail file in perl when copytruncate is used

問題

我創建了一個簡單的perl腳本來讀取日志文件並異步處理數據。
reading子節點還檢查inode編號的變化,以便在日志旋轉時創建新的文件句柄。

我面臨的問題是,在logrotation中使用copytruncate時,旋轉文件時inode不會改變。
這不應該是一個問題,因為腳本應該繼續讀取文件,但是由於某些我無法立即看到的原因,一旦日志輪轉,就不會再讀取新行了。


我如何修改以下腳本(或完全廢棄並重新啟動),以連續copytruncate使用perl使用copytruncate進行logrotated的文件?


use strict;
use warnings;

use threads;
use Thread::Queue;
use threads::shared;

my $logq = Thread::Queue->new();
my %Servers :shared;
my %servername :shared;

#########
#This sub just reads the data off the queue and processes it, i have
#reduced it to a simple print statement for simplicity.
#The sleep is to prevent it from eating cpu.
########

sub process_data
{
        while(sleep(5)){
                if ($logq->pending())
                {
                        while($logq->pending() > 0){
                                my $data = $logq->dequeue();
                                print "Data:$data\n";
                        }
                }
        }
}

sub read_file
{
        my $myFile=$_[0];
        #Get the argument and assign to var.

        open(my $logfile,'<',$myFile) || die "error";
        #open file

        my $Inode=(stat($logfile))[1];
        #Get the current inode

        seek $logfile, 0, 2;
        #Go to the end of the file

        for (;;) {
                while (<$logfile>) {
                        chomp( $_ );
                        $logq->enqueue( $_ );
                        #Add lines to queue for processing

                }
                sleep 5;
                if($Inode != (stat($myFile))[1]){
                        close($logfile);
                        while (! -e $myFile){
                                sleep 2;
                        }
                        open($logfile,'<',$myFile) || die "error";
                        $Inode=(stat($logfile))[1];
                }
                #Above checks if the inode has changed and the file exists still

                seek $logfile, 0, 1;
                #Remove eof

        }

}


my $thr1 = threads->create(\&read_file,"test");
my $thr4 = threads->create(\&process_data);
$thr1->join();
$thr4->join();
#Creating the threads, can add more log files for processing or multiple processing sections.

可能相關的信息

logrotate的日志配置包含

compress
compresscmd /usr/bin/bzip2
uncompresscmd /usr/bin/bunzip2
daily
rotate 5
notifempty
missingok
copytruncate

該文件。

眼鏡

GNU bash, version 3.2.57(1)-release (s390x-ibm-linux-gnu)
perl, v5.10.0
(if logrotate has version and someone knows how to check then i will also add that)

需要更多信息只是問。

因此,當您查看copytruncate ,失敗的原因非常明顯,它會復制原始文件,然后截斷當前文件。
盡管這確保保留了索引節點,但它又產生了另一個問題。

按照我當前尾部處理文件的方式,只需停留在末尾並刪除eof標志,這意味着當文件被截斷時,指針停留在截斷前的最后一行的位置,這又意味着不再有行將被讀取,直到再次到達該指針。

顯而易見的解決方案是簡單地檢查文件的大小,並在指針指向文件末尾時重置指針。

我發現使用下面的兩行代碼來檢查文件大小是否變得更容易。

my $fileSize=(stat($logfile))[7];
#Added after the inode is assigned

和改變

if($Inode != (stat($myFile))[1]){

if($Inode != (stat($myFile))[1] || (stat($myFile))[7] < $fileSize){

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM