2009-08-18 33 views

cevap

8

içeren ekrana dosya ve çıkış şeye yazıldığı gibi her yeni çizgi ayrıştırmak olacak komut dosyası:

def watch_for(file,pattern) 
    f = File.open(file,"r") 

    # Since this file exists and is growing, seek to the end of the most recent entry 
    f.seek(0,IO::SEEK_END) 

    while true 
     select([f]) 
     puts "Found it!" if f.gets =~ pattern 
    end 
end 

Sonra gibi çağrı:

watch_for("some_file", /ERROR/) 

ben hata denetimlerini elided ettik ve bu tür - bunu yapmak isteyecektir ve muhtemelen bazı mecha nizmden kurtulmak için nizm. Ama temel fikir var. Eğer gerçekten nedense Ruby komut dosyası olmak istedim sürece Linux üzerinde iseniz

4

...

tail -f log/development.log | grep "ERROR" 

.

+0

Kaydırma'yı size tepki yeteneği verir Bir hatayı daha anlamlı bir şekilde, meydana geldiğini belirtmekten daha çok. işlem yapmak istediğinizde grepping iyidir, ancak dinamik davranışı başlatma yeteneğinde oldukça sınırlıdır. – ezpz

+0

"... yeni satır" ERROR "dizgesini içerdiğinde ekrana bir şey çıkarır dinamik davranış değildir :) – cakeforcerberus

+1

Bu benim için en iyi şekilde çalışır. Hata günlüğünün etrafındaki meta-programlama, başka yerlerde daha iyi harcanan çabaya benziyor. – MattC

17
def watch_for(file, pattern) 
    f = File.open(file,"r") 
    f.seek(0,IO::SEEK_END) 
    while true do 
    select([f]) 
    line = f.gets 
    puts "Found it! #{line}" if line=~pattern 
    end 
end 

watch_for("g.txt",/ERROR/) 

Ezpz'nin fikri için teşekkürler, seçme yöntemini kullanarak istediğinizi elde edersiniz. Seçme yöntemi, IO akışını dinliyor, baytları 'geç' olanları okuyor.

+2

Not: 'select' her zaman bir dosya akışında kullanıldığında hemen döner: Bu dosya akışından her zaman EOF okuyabilirsiniz, bu yüzden ruby ​​işleminizin, dosyanın güncellenmesini beklerken dönmesini sağlar. Farklı işletim sistemleri dosyaları beklemek için farklı araçlar sunma eğilimindedir, Linux inotify ve OS X'in elverişli olduğu durumlar da vardır - bunları da yakan uygun yakut mücevherleri vardır. – antifuchs

+1

-1% 100 CPU kullanan aptalca bir çözüm. –

+0

Sanırım% 100 CPU'nun kullanılmasının sebebi, eğer 'eğer satır = ~ desen' yazan satırı kaldırırsanız, yeni bir güncelleme olmasa bile boş satırları döndürmeyi sürdürür. Sadece bu konuda da tökezlediğim için kendimi nasıl tamir edeceğimi bilmiyorum. – Pred

3

çek dışarı file-tail mücevher hızlı şeyler için

3

Kötü adamın yaklaşımı:

  1. ile

    ARGF.each do |line| 
        ... 
    
  2. Running ekran yapan bir Ruby komut dosyası:

    tail -f file | ruby script 
    
5

iki yaklaşım vardır:

  • anket sonsuz döngüye dosyası (Qianjigui yanıtında olduğu gibi, ancak sonsuz döngüye içindeki bazı sleep koymak iyidir)
  • kullanım OS olay alt sistemi: kqueue BSD üzerinde, Linux

Bu konuda yazdığım bir makale: Ruby for Admins: Reading Growing Files.

def tail_dash_f(filename) 
    open(ARGV.first) do |file| 
    file.read   
    case RUBY_PLATFORM # string with OS name, like "amd64-freebsd8" 
    when /bsd/, /darwin/ 
     require 'rb-kqueue' 
     queue = KQueue::Queue.new  
     queue.watch_file(ARGV.first, :extend) do 
     yield file.read    
     end 
     queue.run      
    when /linux/ 
     require 'rb-inotify' 
     queue = INotify::Notifier.new 
     queue.watch(ARGV.first, :modify) do 
     yield file.read    
     end 
     queue.run      
    else 
     loop do   
     changes = file.read 
     unless changes.empty? 
      yield changes 
     end 
     sleep 1.0  
     end 
    end 
    end 
end 

tail_dash_f ARGV.first do |data| 
    print data 
    if data =~ /error/i 
    # do something else, for example send an email to administrator 
    end 
end 
1

@Qianjigui fikrine Çalışma ancak 100% CPU kullanmayan: Yani olay alt sistemi ve yoklama birleştirerek programı şöyle bir komut dosyasında bu

def watch_for(file, pattern) 
    # Replace -n0 with -n+1 if you want to read from the beginning of file 
    f = IO.popen(%W[tail -f -n0 #{file}]) 
    loop do 
    select([f]) 
    while line = f.gets 
     puts "Found it! #{line}" if line =~ pattern 
    end 
    end 
end 

watch_for('g.txt', /ERROR/) 
İlgili konular