2013-06-03 9 views
9

के परिणाम लिखें मुझे यकीन है कि कैसे करने के लिए शब्द यह तो मैं इसे बाहर टाइप करेंगे और फिर से संपादित करें और किसी भी सवाल है कि आने का जवाब नहीं कर रहा हूँ ..पीछा लॉग फाइल और नई फ़ाइल

वर्तमान में अपने स्थानीय नेटवर्क डिवाइस पर (PHP4 आधारित) मैं इसका उपयोग एक लाइव सिस्टम लॉग फ़ाइल को पूंछ करने के लिए कर रहा हूं: http://commavee.com/2007/04/13/ajax-logfile-tailer-viewer/

यह अच्छी तरह से काम करता है और प्रत्येक 1 सेकंड यह एक बाहरी पृष्ठ (logfile.php) लोड करता है जो tail -n 100 logfile.log करता है स्क्रिप्ट कोई नहीं करता बफरिंग ताकि परिणाम स्क्रीन पर प्रदर्शित होने वाले परिणाम लॉग फ़ाइल से अंतिम 100 लाइनें हैं।

logfile.php शामिल हैं:

<? // logtail.php $cmd = "tail -10 /path/to/your/logs/some.log"; exec("$cmd 2>&1", $output); 
foreach($output as $outputline) { 
echo ("$outputline\n"); 
} 
?> 

इस भाग में अच्छी तरह से काम कर रहा है।

मैं logfile.php पेज ढाल लिया है, एक नया पाठ फ़ाइल में $ outputline लिखने के लिए बस fwrite($fp,$outputline."\n");

का उपयोग कर जबकि इस काम करता है मुझे लगता है कि बनाई गई है नई फ़ाइल में दोहराव के साथ मुद्दों कर रहा हूँ।

स्पष्ट रूप से प्रत्येक बार पूंछ-एन 100 रन उत्पन्न होता है, अगली बार जब यह चलता है तो यह कुछ समान लाइनों का उत्पादन कर सकता है, क्योंकि यह दोहराता है कि मैं नई टेक्स्ट फ़ाइल में डुप्लिकेशंस की कई पंक्तियों के साथ समाप्त कर सकता हूं।

मैं पिछली लाइनों पर लिखने वाली लाइन की तुलना सीधे तुलना नहीं कर सकता क्योंकि समान मिलान हो सकते हैं।

क्या कोई तरीका है कि मैं पिछले ब्लॉक के साथ 100 लाइनों के इस मौजूदा ब्लॉक की तुलना कर सकता हूं और फिर केवल उन पंक्तियों को लिख सकता हूं जो मिलान नहीं कर रहे हैं .. फिर से संभव है कि ब्लॉकबी में समान रेखाएं होंगी जो आवश्यक हैं ..

क्या लॉगफाइल.एफ़पी अपडेट करना संभव है कि यह आखिरी बार मेरे लॉगफाइल में ली गई स्थिति को नोट करें और फिर वहां से अगले 100 लाइनें पढ़ें और उन्हें नई फ़ाइल में लिखें?

लॉग फ़ाइल 500MB तक हो सकता है तो मैं यह सब हर बार में पढ़ने के लिए नहीं करना चाहते हैं ..

कोई सलाह या सुझाव का स्वागत करते हैं ..

धन्यवाद

अद्यतन @ 16 :

$file = "/logs/syst.log"; 
$handle = fopen($file, "r"); 

if(isset($_SESSION['ftell'])) { 
    clearstatcache(); 
    fseek($handle, $_SESSION['ftell']); 

    while ($buffer = fgets($handle)) { 
     echo $buffer."<br/>"; 
     @ob_flush(); @flush(); 
    } 

    fclose($handle); 
    @$_SESSION['ftell'] = ftell($handle);   
} else { 
    fseek($handle, -1024, SEEK_END); 
    fclose($handle); 
    @$_SESSION['ftell'] = ftell($handle); 
} 
: 30

मैं इन सबसे छुटकारा इस काम के उपयोग करते हुए मिल गया है 10

ऐसा लगता है, लेकिन यह पूरी फ़ाइल को पहले लोड करता है और फिर केवल अपडेट लोड करता है।

मैं इसे अंतिम 50 लाइनों के साथ कैसे शुरू करूंगा और फिर केवल अपडेट?

धन्यवाद :)

अद्यतन 2013/04/06 जबकि इस काम करता है यह बड़ी फ़ाइलों के साथ बहुत धीमी है।

मैंने इस कोड को आजमाया है और यह तेज़ लगता है, लेकिन यह केवल यह कहां से नहीं छोड़ा जाता है।

function last_lines($path, $line_count, $block_size = 512){ 
    $lines = array(); 

    // we will always have a fragment of a non-complete line 
    // keep this in here till we have our next entire line. 
    $leftover = ""; 

    $fh = fopen($path, 'r'); 
    // go to the end of the file 
    fseek($fh, 0, SEEK_END); 
    do{ 
     // need to know whether we can actually go back 
     // $block_size bytes 
     $can_read = $block_size; 
     if(ftell($fh) < $block_size){ 
      $can_read = ftell($fh); 
     } 

     // go back as many bytes as we can 
     // read them to $data and then move the file pointer 
     // back to where we were. 
     fseek($fh, -$can_read, SEEK_CUR); 
     $data = fread($fh, $can_read); 
     $data .= $leftover; 
     fseek($fh, -$can_read, SEEK_CUR); 

     // split lines by \n. Then reverse them, 
     // now the last line is most likely not a complete 
     // line which is why we do not directly add it, but 
     // append it to the data read the next time. 
     $split_data = array_reverse(explode("\n", $data)); 
     $new_lines = array_slice($split_data, 0, -1); 
     $lines = array_merge($lines, $new_lines); 
     $leftover = $split_data[count($split_data) - 1]; 
    } 
    while(count($lines) < $line_count && ftell($fh) != 0); 
    if(ftell($fh) == 0){ 
     $lines[] = $leftover; 
    } 
    fclose($fh); 
    // Usually, we will read too many lines, correct that here. 
    return array_slice($lines, 0, $line_count); 
} 

किसी भी तरह से इसे संशोधित किया जा सकता है ताकि यह अंतिम ज्ञात स्थिति से पढ़ा जा सके ..?

धन्यवाद

+1

मेरी पहली है है सुझाव PHP को अपग्रेड करना होगा। http://php.net/eol.php – vascowhite

+0

दुर्भाग्य से यह संभव नहीं है।यह डिवाइस में एम्बेडेड है :( – MacMan

+0

क्या उपकरण पर्ल चला सकता है? यह एक महाकाव्य एक-लाइनर हो सकता है .. –

उत्तर

0

उपयोग tail -c <number of bytes, लाइनों की संख्या के बजाय, और फिर फ़ाइल आकार की जाँच करें। किसी न किसी विचार है:

$old_file_size = 0; 
$max_bytes = 512; 

function last_lines($path) { 
    $new_file_size = filesize($path); 
    $pending_bytes = $new_file_size - $old_file_size; 
    if ($pending_bytes > $max_bytes) $pending_bytes = $max_bytes; 
    exec("tail -c " + $pending_bytes + " /path/to/your_log", $output); 
    $old_file_size = $new_file_size; 
    return $output; 
} 

लाभ यह है कि आप सभी विशेष प्रसंस्करण सामान के साथ भाग कर सकते हैं, और अच्छा प्रदर्शन मिलता है। नुकसान यह है कि आपको आउटपुट को लाइनों में मैन्युअल रूप से विभाजित करना होगा, और शायद आप अधूरा लाइनों के साथ समाप्त हो सकते हैं। लेकिन यह एक बड़ा सौदा नहीं है, आप उत्पादन से अकेले अंतिम पंक्ति को छोड़कर आसानी से काम कर सकते हैं (और old_file_size से बाइट्स की अंतिम पंक्ति संख्या को उचित रूप से घटाना)।

1

वास्तव में आप कैसे उत्पादन का उपयोग करना चाहते पर स्पष्ट नहीं है, लेकिन होता यह काम की तरह कुछ ....

$dat = file_get_contents("tracker.dat"); 
$fp = fopen("/logs/syst.log", "r"); 
fseek($fp, $dat, SEEK_SET); 
ob_start(); 
// alternatively you can do a while fgets if you want to interpret the file or do something 
fpassthru($fp); 
$pos = ftell($fp); 
fclose($fp); 
echo nl2br(ob_get_clean()); 
file_put_contents("tracker.dat", ftell($fp)); 

tracker.dat सिर्फ एक पाठ फ़ाइल है कि जहां पढ़ने स्थिति स्थिति से किया गया है पिछला रन मैं सिर्फ उस स्थिति की तलाश कर रहा हूं और बाकी को आउटपुट बफर में पाइप कर रहा हूं।

2

परिचय

आप अंतिम स्थिति पर नज़र रखने से एक फ़ाइल पूंछ कर सकते हैं,

उदाहरण

$file = __DIR__ . "/a.log"; 
$tail = new TailLog($file); 
$data = $tail->tail(100) ; 
// Save $data to new file 

TailLog एक साधारण वर्ग मैं इस कार्य को यहां के लिए लिखा था अपने वास्तव में फ़ाइल

सरल टेस्ट पीछा दिखाने के लिए एक सरल उदाहरण है है

$file = __DIR__ . "/a.log"; 
$tail = new TailLog($file); 

// Some Random Data 
$data = array_chunk(range("a", "z"), 3); 

// Write Log 
file_put_contents($file, implode("\n", array_shift($data))); 

// First Tail (2) Run 
print_r($tail->tail(2)); 

// Run Tail (2) Again 
print_r($tail->tail(2)); 

// Write Another data to Log 
file_put_contents($file, "\n" . implode("\n", array_shift($data)), FILE_APPEND); 

// Call Tail Again after writing Data 
print_r($tail->tail(2)); 

// See the full content 
print_r(file_get_contents($file)); 

आउटपुट

// First Tail (2) Run 
Array 
(
    [0] => c 
    [1] => b 
) 

// Run Tail (2) Again 
Array 
(
) 

// Call Tail Again after writing Data 
Array 
(
    [0] => f 
    [1] => e 
) 

// See the full content 
a 
b 
c 
d 
e 
f 

रीयल टाइम पीछा

while(true) { 
    $data = $tail->tail(100); 
    // write data to another file 
    sleep(5); 
} 

नोट: 100 लाइनों पीछा मतलब यह नहीं है यह हमेशा 100 लाइनों लौट आते हैं। यह नई लाइनों को वापस लाएगा 100 वापस लौटने के लिए लाइनों की अधिकतम संख्या है। यह कुशल नहीं हो सकता है जहाँ आप प्रति सेकंड 100 से अधिक लाइन की भारी प्रवेश किसी भी

पूंछ कक्षा

class TailLog { 
    private $file; 
    private $data; 
    private $timeout = 5; 
    private $lock; 

    function __construct($file) { 
     $this->file = $file; 
     $this->lock = new TailLock($file); 
    } 

    public function tail($lines) { 
     $pos = - 2; 
     $t = $lines; 
     $fp = fopen($this->file, "r"); 
     $break = false; 
     $line = ""; 
     $text = array(); 

     while($t > 0) { 
      $c = ""; 

      // Seach for End of line 
      while($c != "\n" && $c != PHP_EOL) { 
       if (fseek($fp, $pos, SEEK_END) == - 1) { 
        $break = true; 
        break; 
       } 
       if (ftell($fp) < $this->lock->getPosition()) { 
        break; 
       } 
       $c = fgetc($fp); 
       $pos --; 
      } 
      if (ftell($fp) < $this->lock->getPosition()) { 
       break; 
      } 
      $t --; 
      $break && rewind($fp); 
      $text[$lines - $t - 1] = fgets($fp); 
      if ($break) { 
       break; 
      } 
     } 

     // Move to end 
     fseek($fp, 0, SEEK_END); 

     // Save Position 
     $this->lock->save(ftell($fp)); 

     // Close File 
     fclose($fp); 
     return array_map("trim", $text); 
    } 
} 

पूंछ ताला

class TailLock { 
    private $file; 
    private $lock; 
    private $data; 

    function __construct($file) { 
     $this->file = $file; 
     $this->lock = $file . ".tail"; 
     touch($this->lock); 

     if (! is_file($this->lock)) 
      throw new Exception("can't Create Lock File"); 

     $this->data = json_decode(file_get_contents($this->lock)); 

     // Check if file is valida json 
     // Check if Data in the original files as not be delete 
     // You expect data to increate not decrease 

     if (! $this->data || $this->data->size > filesize($this->file)) { 
      $this->reset($file); 
     } 
    } 

    function getPosition() { 
     return $this->data->position; 
    } 

    function reset() { 
     $this->data = new stdClass(); 
     $this->data->size = filesize($this->file); 
     $this->data->modification = filemtime($this->file); 
     $this->data->position = 0; 
     $this->update(); 
    } 

    function save($pos) { 
     $this->data = new stdClass(); 
     $this->data->size = filesize($this->file); 
     $this->data->modification = filemtime($this->file); 
     $this->data->position = $pos; 
     $this->update(); 
    } 

    function update() { 
     return file_put_contents($this->lock, json_encode($this->data, 128)); 
    } 
} 
संबंधित मुद्दे