/ / Czytanie pliku, który może być obcięty w Perlu - perl, plik-io, obcięty

Czytanie pliku, który może być obcięty w Perlu - perl, plik-io, obcięty

Używam Perla do odczytania pliku dziennika, którymoże być obcięte w dowolnym momencie. Jeśli tak się stanie, chcę rozpocząć czytanie pliku na początku, ale domyślne zachowanie Perla wydaje się czekać, aż wskaźnik pliku zostanie wykryty. Na przykład, jeśli uruchomię następujące elementy:

perl -e "open FILE, "test"; while (1) { $line = <FILE>; print "$line"; }"

a następnie:

for i in 1 2 3; do echo $i >> test; done
:>test
for i in 4 5 6 7; do echo $i >> test; done

wynik, który otrzymuję, to:

1
2
3
7

Ale gdybym zrobił to samo, zastępując kod Perla:

tail -f test

następnie (ignorując ogon na stderr) otrzymuję wyjście, które chcę, tj .:

1
2
3
4
5
6
7

Oczywiście, nie mogę po prostu użyć ogona, ponieważ chcę wykonać pewne przetwarzanie w samej linii. Jedna myśl, którą miałem, to połączenie dwóch:

tail -f test | perl -e "while (1) { $line = <STDIN>; print "$line"; }"

który działa na mojej maszynie programującej Linuksa, ale niestety nie na platformie docelowej Solaris.

Jakieś pomysły?

Zgodnie z prośbą przykład użycia File :: Tail jest następujący:

perl -e "use File::Tail; $file = File::Tail->new("test"); while (defined($line=$file->read)) { print "$line"; }"

Jeśli następnie wprowadzę dane do testu, tak jak poprzednio, wyjście, które otrzymuję, jest po prostu:

7

co oczywiście nie jest pożądane. "Próbowałem dostosować maxinterval, że File :: Tail będzie czekać w następujący sposób:

perl -e "use File::Tail; $file = File::Tail->new(name => "test", maxinterval => 1); while (defined($line=$file->read)) { print "$line"; }"

ale w takim przypadku zbyt szybkie wprowadzanie danych do pliku testowego, na przykład:

for i in 1 2 3; do echo $i >> test; done; :>test; for i in 4 5 6 7; do echo $i >> test; done

w wyniku:

4
5
6
7

Niestety, jest to realistyczny scenariusz dlanasza (bardzo zajęta) aplikacja. Dla porównania, Linux wydaje się poprawnie obsługiwać tego rodzaju prędkość wprowadzania danych, więc jest całkiem jasne, że można to zrobić (chociaż być uczciwym, może nie w Perlu ....?)

Odpowiedzi:

2 dla odpowiedzi № 1

The Linux tail dowództwo używa inotify mechanizm monitorowania zmian w pliku bez konieczności wielokrotnego odpytywania o aktualizacje. Pozwala to szybko i niezawodnie reagować na wszelkie zmiany w pliku.

Aby zaimplementować podobną funkcjonalność w Perlu, możesz użyć Linux :: Inotify2 moduł z CPAN. Niestety, jak sama nazwa wskazuje, ten moduł działa tylko na Linuksie, więc nie pomoże ci w przeniesieniu twojego skryptu do Solaris.

ty moc móc używać FAM z SGI :: FAM moduł zamiast; może się wewnętrznie wycofaćdo sondowania, jeśli nie ma natywnego mechanizmu powiadomienia o zmianie pliku, ale przynajmniej powinien zapewnić rozsądnie dobrą i przetestowaną implementację odpytywania plików.


1 dla odpowiedzi nr 2

Wygląda na to, że chcesz naśladować tail w Perlu.

  • Jeśli masz dostęp do CPAN, możesz użyć File::Tail.

    Jest to czysty Perl (nie XS), dzięki czemu można zobaczyć, jak jest on zaimplementowany w źródle jeśli nie ma dostępu do CPAN.

  • Zobacz także PerlFAQ5 ("Jak zrobić ogon -f w perlu?")