2014-08-27 14 views
5

o logrotated sonra bile sürekli dosyayı okumak logrotate, logrotate tarafından döndürüldükten sonra?piton: Ben</p> <pre><code>while True: line = f.readline() if line: print line, else: time.sleep(0.1) </code></pre> <p>nasıl hala okuyabilir emin olabilirsiniz (<code>tail -f</code> aynı) Ben sürekli günlük dosyası okumak basit python komut dosyası var

Örnek olarak, tail -F'un ne yapması gerektiğini de yapmalıyım. Ben

+0

Muhtemelen bir kopya, ama kesinlikle ilgili: http://stackoverflow.com/q/25413115/1639625 –

+0

Bunu yapan bir tarif var burada (http://code.activestate.com/recipes/577968- log-kuyruk-f izleyici-log /). Yine de kendim için denemedim. – dano

cevap

8

Yalnızca Unix'te yapmayı planladığınız sürece, en sağlam yol, açık dosyanın yine de i-node adıyla aynı şekilde başvurduğunu ve artık geçerli olmadığında yeniden açılacağını kontrol etmektir. Dosyanın i-numarasını os.stat ve os.fstat alanından st_ino alanına alabilirsiniz.

Bu gibi görünebilir:

import os, sys, time 

name = "logfile" 
current = open(name, "r") 
curino = os.fstat(current.fileno()).st_ino 
while True: 
    while True: 
     buf = current.read(1024) 
     if buf == "": 
      break 
     sys.stdout.write(buf) 
    try: 
     if os.stat(name).st_ino != curino: 
      new = open(name, "r") 
      current.close() 
      current = new 
      curino = os.fstat(current.fileno()).st_ino 
      continue 
    except IOError: 
     pass 
    time.sleep(1) 

Bu Windows üzerinde çalışır şüphe, ancak tail açısından konuşurken beri, bu bir sorun değil tahmin ediyorum. :)

4

python 2.7 kullanıyorum

Sen dosyada olduğu takip ve okumak istediğiniz zaman yeniden açmak suretiyle yapabilirsiniz. Günlük dosyası döndüğünde, dosyanın daha küçük olduğunu ve yeniden açtığınız için herhangi bir bağlantıyı kaldırdığınızı görürsünüz.

import time 

cur = 0 
while True: 
    try: 
     with open('myfile') as f: 
      f.seek(0,2) 
      if f.tell() < cur: 
       f.seek(0,0) 
      else: 
       f.seek(cur,0) 
      for line in f: 
       print line.strip() 
      cur = f.tell() 
    except IOError, e: 
     pass 
    time.sleep(1) 

Bu örnek Böyle bir dosya mevcut değildir zaman küçük süreler olarak logrotate detayların emin değilim çünkü bulunmayan dosya gibi hatalar gizler.

+0

çok teşekkürler. Merak ediyorum, eğer daha iyi/daha zarif bir çözüm varsa. Örneğin, dosya dosyam 'f' hala' file.log' dosyasına işaret edip etmediğimi kontrol etmenin herhangi bir yolu var mı? Dosya tanıtıldıktan sonra, dosya tanıtıcısı eski dosyaya işaret edecektir, yeni 'file.log' için değil –

+0

Dosya işlemleri ilgili IMHO söz konusu olduğunda oldukça zariftir. Sorun şu ki, dosyayı açık tutarsanız, dosya tanıtıcısı yeni dosyaya değil, döndürülmüş dosyaya işaret etmeye devam eder. Orijinal dosya adını tekrar kontrol etmeden, bunun eski olduğunu söyleyemezsiniz. Alternatif bir yaklaşım, dosya işlemleri hakkında sizi bilgilendirecek olan inotify'ı kullanmaktır. Daha karmaşık ama aynı zamanda iyi bir yaklaşım. – tdelaney

0

@tdelaney ve @ Dolda2000'in cevapları sayesinde, neyi takip ettim. Hem Linux hem de Windows üzerinde çalışmalı ve aynı zamanda logrotate'ın copytruncate veya create seçeneklerini de kullanmalıdır (sırasıyla kopyalayın, sonra da kesilmiş boyutu 0'a getirin ve sonra dosyayı yeniden oluşturun).

file_name = 'my_log_file' 
seek_end = True 
while True: # handle moved/truncated files by allowing to reopen 
    with open(file_name) as f: 
     if seek_end: # reopened files must not seek end 
      f.seek(0, 2) 
     while True: # line reading loop 
      line = f.readline() 
      if not line: 
       try: 
        if f.tell() > os.path.getsize(file_name): 
         # rotation occurred (copytruncate/create) 
         f.close() 
         seek_end = False 
         break 
       except FileNotFoundError: 
        # rotation occurred but new file still not created 
        pass # wait 1 second and retry 
       time.sleep(1) 
      do_stuff_with(line) 

bir sınırlama copytruncate seçeneğini kullanarak zaman uyku ve rotasyon, son satırları "kayıp" olacak önce uyandırma gerçekleşir ise hatları (dosyasına eklenir eğer hala olacağıdır Şimdi "eski" günlük dosyasında, ancak bu dosyayı okumak için "takip" için iyi bir yol göremiyorum). Bu sınırlama, f tanımlayıcısının yeniden adlandırılan dosyaya işaret edeceğinden ve bu nedenle tanımlayıcı kapatılmadan ve yeniden açılmadan önce son satırların okunacağından "taşıma ve oluşturma" create seçeneği ile ilgili değildir.

İlgili konular