tail -f, ale z numerami linii


21

Próbuję zobaczyć, ile razy foo barpojawia się w /var/log/foo.logdowolnym czasie na zdalnym serwerze, ale nic, co do tej pory próbowałem, nie zadziałało.

Mam już skrypt timera, którego używam do śledzenia, ile czasu minęło, odkąd zacząłem tailing /var/log/foo.log, a teraz chciałbym po prostu powiedzieć, ile razy foo barpojawił się w wynikach tailed.

Szukałem w Google, ale nie znalazłem nic istotnego na pierwszych 10 stronach wyników.

Oto, co próbowałem z frustrującymi wynikami:

## works on local machine, but doesn't work as expected on remote
tail -f /var/log/foo.log | grep foo\ bar | sed '='

## works on local, but not remote
tail -f /var/log/foo.log | grep foo\ bar | cat -n -

##  works on local, but not remote
tail -f /var/log/foo.log | grep foo\ bar | awk -F'\n' '{printf "[%d]> ", NR; print $1}'

Próbowałem nawet napisać scenariusz sed, który zachowywałby się w ten sposób tail -f, ale zrobiłem z tego postępy.

UWAGA

na zdalnym serwerze działa starsza wersja coreutils, a aktualizacja jest opcją, ale NIE jest w żaden sposób pożądanym rozwiązaniem.


2
W jaki sposób to nie działa? Wypróbuj --line-bufferedopcję grep. Lubtail -f ... | awk '/foo bar/{print ++n, $0}'
Stéphane Chazelas

Dlaczego nie działa na pilocie? Przykład:tail -f /var/log/log.log | awk '{ printf "[%d]> %s\n", NR+1 ,$0; fflush(stdout); }'

Odpowiedzi:


29
tail -f | nl

działa dla mnie i jest to pierwsze, o czym myślałem - to znaczy, jeśli naprawdę chcesz, aby wiersze były ponumerowane od 1, a nie z rzeczywistym numerem wiersza z oglądanego pliku. Opcjonalnie dodaj w greprazie potrzeby w odpowiednim miejscu (przed lub po nl). Pamiętaj jednak, że może wystąpić buforowanie. W moim szczególnym przypadku grepma --line-bufferedopcję, ale nlbuforuje dane wyjściowe i nie ma opcji, aby ją wyłączyć. W związku z tym tail | nl | grepkombinacja naprawdę nie ładnie płynie.

To mówi,

tail -f | grep -n pattern

działa również dla mnie. Numeracja zaczyna się od początku „tailing”, a nie od początku całego pliku dziennika.


wersja grep działająca na serwerze nie ma -nopcji.
Alexej Magura,

ma jednak długą opcję --line-number: tail -f /var/log/foo.log | grep foo\ bar --line-numberdziała!
Alexej Magura,

1
To interesujące - nie sprawdziłem POSIX jako takiego, ale strona podręcznika GNU grep mówi: -n jest określone przez POSIX .
Peter

16

Myślę, że tak jest lepiej ..

less -N +F <filepath>

2
Czy możesz wyjaśnić, dlaczego uważasz, że jest lepiej?
Navigatron,

To duża edycja, cofam.
Adam Eberlin

3
Pokazuje numer linii jako odniesienie dla całego pliku. tail -f | nl pokazuje numer linii jako odniesienie pierwszego wyjścia ogona.
rafaelvalle

Jest to bardzo przydatne i odnosi się do tytułu PO, ale nie do ich pytania . Chcieli wiedzieć, ile razy X pojawia się w pliku: P
Timmah

6

Możesz również przesłać dane wyjściowe do lessniego, ma on funkcję numeru linii, -Nktóra pozwala przewijać dziennik w tę iz powrotem.

$ tail -f /var/log/foo.log | less -N

Przykład

  1 Jan 17 22:11:58 greeneggs fprintd[4323]: ** Message: entering main loop
  2 Jan 17 22:12:01 greeneggs su: (to root) saml on pts/5
  3 Jan 17 22:12:28 greeneggs fprintd[4323]: ** Message: No devices in use, exit
  4 Jan 17 22:12:56 greeneggs gnome-session[1876]: 22:12:56 | Git | personal_repo | Checking for remote changes...
  5 Jan 17 22:12:56 greeneggs gnome-session[1876]: 22:12:56 | Cmd | personal_repo | git rev-parse HEAD
  6 Jan 17 22:12:56 greeneggs gnome-session[1876]: 22:12:56 | Cmd | personal_repo | git ls-remote --heads --exit-code "ssh://sam@sparkleshare.jake      
  6 8us.org/home/sam/SparkleShare/personal_repo.git" master
  7 Jan 17 22:12:58 greeneggs gnome-session[1876]: X11 forwarding request failed on channel 1
  8 Jan 17 22:12:58 greeneggs gnome-session[1876]: 22:12:58 | Git | personal_repo | No remote changes, local+remote: 532213be48cce3b93cb177d409faa      
  8 03b71d0cfa5
  9 Jan 17 22:13:35 greeneggs gnome-session[1876]: 22:13:35 | ListenerTcp | Pinging tcp://notifications.sparkleshare.org:443/
 10 Jan 17 22:13:35 greeneggs gnome-session[1876]: 22:13:35 | ListenerTcp | Received pong from tcp://notifications.sparkleshare.org:443/

UWAGA: Zwróć uwagę na wynik. Ta funkcja może Ci się nie podobać lub nie, ale zajmie to długie linie i pokroi je, aby mogły przejść do następnej linii, ale nadal zachowają ten sam odpowiedni numer linii. Uważam tę funkcję za nieocenioną podczas analizy szerokich plików dziennika! Możesz zobaczyć efekt tej funkcji w wierszach 6 i 8 .


To jest niejasne. Gdzie jest podana nazwa pliku? Należy to wyjaśnić, zauważając, że dane wyjściowe są ponumerowane od 1, zaczynając od ostatnich 10 wierszy nazwy pliku, ponieważ jest to zachowanie domyślne tail. Jeśli chodzi o długie linie, to zachowanie jest przełączane podczas lessużywania -S.
ILMostro_7,

2

Aby grepować nowe wiersze tylko w pliku dziennika, ponieważ pochodzą z numerem wiersza, możesz:

{
  initial_lines=$(wc -l)
  tail -n +1 -f | awk -v NR="$initial_lines" '/pattern/{print NR": "$0}'
} < file.log

(z mawk, będziesz chciał dodać -Winteractiveopcję, aby zapobiec buforowaniu danych wejściowych (!)).

wc -lodczytuje linie , które już tam były i liczy je (znaki nowej linii, co oznacza, że ​​nadal działa, nawet jeśli ostatnia linia nie jest jeszcze pełna), a następnie my tail -fresztę (zaczynając od miejsca, w którym wcprzestał czytać) i określamy, awkjaki jest numer linii pierwszy, który zobaczy.


wybranie lnazwy zmiennej zmusiło mnie do zmrużenia oczu na $ l, myśląc, że to $1^^ (ale jak wiem (i 100% ufam), przeczytałem ponownie i zobaczyłem prawdę). Dla ciekawości: aby uniknąć pewnego „warunku wyścigu” między wc -li tail -f(jeśli plik rośnie szybko, można odrzucić niektóre linie, a zatem NR zaczyna się od niewłaściwej liczby), czy można $lzamiast tego pominąć linie? (i jaki jest limit ogonów -nw posiksach i GNU?). Może z tymczasowym plikiem pośrednim?
Olivier Dulac

@OlivierDulac, tail -n +1(czytaj wszystko z pozycji początkowej) rozwiązuje problemy związane z wyścigiem. Odczyta wiersze, które nie były w pliku w chwili wc -lzakończenia, z dokładnej pozycji, która wcgo opuściła. Tak więc NR będzie miał właściwą pozycję bez względu na to, ile wierszy zostało napisanych między wckońcem a tailpoczątkiem. Gdybyś powiedział, tailżeby zacząć od pewnej pozycji względem końca pliku, będziesz miał problemy.
Stéphane Chazelas

och, ciekawe: rzeczywiście dane gromadzą się w stdin, podczas gdy nic ich nie czyta (od końca wc do początku głowy) ... powinienem był to zrozumieć. Dzięki. Teraz rozumiem, dlaczego „<plik”. sprytne, jak zwykle :)
Olivier Dulac

1
@OlivierDulac, o ograniczeniach (które nie dotyczą tail -n +1tutaj), w przypadku zwykłych plików większość implementacji ich nie ma, ponieważ mogą zaczynać od końca i z seekpowrotem, dopóki nie znajdą n-tego nowego wiersza bez konieczności przechowywania więcej niż jednej wartości buf danych w pamięci. W przypadku niewidocznych danych wejściowych możesz napotkać limity. POSIX wymaga implementacji, aby móc przechowywać co najmniej 10 x LINE_MAX bajtów (LINE_MAX to co najmniej 2048). Ogon GNU nie ma limitu innego niż pamięć AFAIK
Stéphane Chazelas

0

Jeśli chcesz numerować od samego początku, potrzebujesz grep -n, aby zastosować się do wszystkich linii.

 tail -f -n100000000 filename.log | grep -n '' 

Jeśli chciałbyś wtedy pokazać tylko 10 ostatnich, pomyślałem, że możesz ponownie ogonić plik:

 tail -f -n100000000 filename.log | grep -n '' | tail -n10

Pierwszy jest przydatny, ale pokazuje zbyt dużą moc wyjściową. Nie wiem, dlaczego drugi nie działa.


Ogon nie ma „pokaż wszystkie linie”, stąd mój 100000000
Martin Cleaver,

1
tail -n +1 -fogon od początku.
Stéphane Chazelas

1
Drugi nie działa, ponieważ najbardziej prawy tailnie może nic wypisać, dopóki nie zobaczy ostatniego wiersza swojego wejścia (skąd miałby wiedzieć, który jest dziesiąty ostatni wiersz?), Który nigdy się nie wydarzy, ponieważ tail -fnigdy się nie kończy.
Stéphane Chazelas

-1

Polecenie cat -n [filename] | tailto szybko policzy i wyświetli najnowsze rekordy, jeśli tego właśnie szukasz.

-fPrzełącznik sprawia, że trwały aż do ucieczki - która naprawdę nie brzmi zastosowanie w scenariuszu lub jest zbędny.

wc -l [filename] otrzyma liczbę linii w celu

wc -l [filenameprefix]* policzy wszystkie wiersze we wszystkich plikach pasujących do wzorca, a nawet poda podsumowanie na końcu.

Pełniejsze szczegóły mogą dać pełniejsze odpowiedzi.


-1

Jest to argument nlub --lines(użyte nieco inaczej, patrz poniżej):

$ tail -f -n 25 /path/to/file.txt

$ tail -f --lines=25 /path/to/file.txt

Zobacz także pomoc:

$ tail --help

1
OP chce numerów linii, a nie kilku linii.
robbat2
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.