queue -f, mais avec des numéros de ligne

21

J'essaie de voir combien de fois foo barapparaît /var/log/foo.logdans un laps de temps arbitraire sur un serveur distant, mais rien de ce que j'ai essayé jusqu'à présent n'a fonctionné.

J'ai déjà un script de minuterie que j'utilise pour garder une trace de combien de temps il s'est écoulé depuis que j'ai commencé la queue /var/log/foo.log, et maintenant je voudrais juste un moyen de dire combien de fois foo barest apparu dans la sortie queue.

J'ai cherché sur Google, mais je n'ai rien trouvé de pertinent dans les 10 premières pages de résultats.

Voici ce que j'ai essayé avec des résultats frustrants:

## 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}'

J'ai même essayé d'écrire un script sed qui agirait comme ça tail -f, mais j'ai fait des progrès limités voire nuls avec cela.

REMARQUE

le serveur distant exécute une ancienne version de coreutils, et la mise à niveau est une option, mais pas en aucune façon la solution désirée.

Alexej Magura
la source
2
De quelle façon ça ne marche pas? Essayez l' --line-bufferedoption pour grep. Outail -f ... | awk '/foo bar/{print ++n, $0}'
Stéphane Chazelas
Pourquoi ça ne marche pas sur la télécommande? Exemple:tail -f /var/log/log.log | awk '{ printf "[%d]> %s\n", NR+1 ,$0; fflush(stdout); }'

Réponses:

29
tail -f | nl

fonctionne pour moi et est le premier à quoi j'ai pensé - c'est-à-dire si vous voulez vraiment que les lignes soient numérotées à partir de 1 et non avec le vrai numéro de ligne du fichier regardé. Ajoutez éventuellement grepsi nécessaire à l'endroit approprié (avant ou après nl). Cependant, n'oubliez pas que la mise en mémoire tampon peut se produire. Dans mon cas particulier, grepa l' --line-bufferedoption, mais met en nlmémoire tampon sa sortie et n'a pas d'option pour désactiver cela. Par conséquent, le tail | nl | grepcombo ne coule pas vraiment bien.

Cela dit,

tail -f | grep -n pattern

fonctionne aussi pour moi. La numérotation recommence à partir du début du "tailing" plutôt qu'au début de tout le fichier journal.

peterph
la source
la version de grep s'exécutant sur le serveur n'a pas d' -noption.
Alexej Magura
il a cependant l'option longue --line-number: ça tail -f /var/log/foo.log | grep foo\ bar --line-numbermarche!
Alexej Magura
1
C'est intéressant - je n'ai pas vérifié POSIX en tant que tel, mais la page de manuel GNU grep dit: -n est spécifié par POSIX .
peterph
16

Je pense que c'est mieux ..

less -N +F <filepath>
Adam Eberlin
la source
2
Pourriez-vous expliquer pourquoi vous pensez que c'est mieux?
Navigatron
Ceci est un gros montage, je reviens.
Adam Eberlin
3
Affiche le numéro de ligne prenant comme référence l'ensemble du fichier. queue -f | nl montre le numéro de ligne en prenant comme référence la première sortie de queue.
rafaelvalle
C'est très pratique et répond au titre du PO mais pas à leur question . Ils voulaient savoir combien de fois X apparaît dans un fichier: P
Timmah
6

Vous pouvez également diriger la sortie vers less, il a une fonction de numéro de ligne, -Nqui vous permettrait de faire défiler d'avant en arrière dans le journal.

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

Exemple

  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://[email protected]      
  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/

REMARQUE: prenez note de la sortie. Vous pouvez ou ne pas aimer cette fonctionnalité, mais cela prendra de longues lignes et les hachera pour qu'elles continuent sur la ligne suivante, tout en conservant le même numéro de ligne correspondant. Je trouve cette fonctionnalité inestimable lors de l'analyse de fichiers journaux qui sont larges! Vous pouvez voir l'effet de cette fonction sur les lignes 6 et 8 .

slm
la source
Ce n'est pas clair. Où le nom de fichier est-il spécifié? Il doit être clarifié, en notant que la sortie est numérotée de 1 en commençant par les 10 dernières lignes du nom de fichier, car c'est le comportement par défaut de tail. En ce qui concerne les longues lignes, ce comportement est basculé dans l' lessutilisation -S.
ILMostro_7
2

Pour récupérer les nouvelles lignes uniquement dans le fichier journal lorsqu'elles sont fournies avec leur numéro de ligne, vous pouvez faire:

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

(avec mawk, vous voulez ajouter l' -Winteractiveoption pour empêcher son entrée (!) mise en mémoire tampon).

wc -llit les lignes qui étaient déjà là et les compte (les caractères de nouvelle ligne ce qui signifie que cela fonctionne même si la dernière ligne n'est pas encore pleine), puis nous tail -fle reste (à partir de l'endroit où la wclecture a été arrêtée) et dire awkquel est le numéro de ligne de le premier qu'il voit.

Stéphane Chazelas
la source
choisir lcomme nom de variable m'a fait plisser les yeux sur $ l, pensant que c'était $1^^ (mais comme je vous connais (et je vous fais confiance à 100%), j'ai relu et vu la vérité). Juste pour la curiosité: pour éviter une "condition de concurrence" entre le wc -let le tail -f(si le fichier se développe rapidement, on peut supprimer certaines lignes et donc le NR commence à partir du mauvais numéro), est-il possible de sauter des $llignes à la place? (et quelle est la limite des queues -nen posix et en gnu?). Peut-être avec un fichier intermédiaire temporaire?
Olivier Dulac
@OlivierDulac, tail -n +1(lire quoi que ce soit depuis la position de départ) répond aux problèmes de condition de course. Il lira les lignes qui n'étaient pas dans le fichier au moment où il s'est wc -lterminé, à partir de la position exacte qui l'a wcquitté. NR aura donc la bonne position quel que soit le nombre de lignes écrites entre la wcfin et le taildébut. C'est si vous avez dit tailde partir d'une position par rapport à la fin du fichier que vous auriez des problèmes.
Stéphane Chazelas
oh, interressant: en effet, les données s'accumulent dans stdin alors que rien ne les lit (entre la fin du wc jusqu'au début de la tête) ... j'aurais dû m'en rendre compte. THX. Maintenant, je vois pourquoi vous "<fichier". intelligent, comme d'habitude :)
Olivier Dulac
1
@OlivierDulac, à propos des limitations (qui ne s'appliquent pas tail -n +1ici), pour les fichiers normaux, la plupart des implémentations n'en ont pas car elles peuvent commencer de la fin seekvers l'arrière jusqu'à ce qu'elles trouvent la nième nouvelle ligne sans avoir à stocker plus d'un buf. des données en mémoire. Pour les entrées non recherchables, c'est là que vous pouvez rencontrer des limites. POSIX nécessite des implémentations pour pouvoir stocker au moins 10 x LINE_MAX octets (LINE_MAX étant au moins 2048). La queue GNU n'a pas d'autre limite que la mémoire AFAIK
Stéphane Chazelas
0

Si vous vouliez numéroter depuis le début, vous auriez besoin de grep -n pour appliquer à toutes les lignes.

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

Si vous ne souhaitiez afficher que les 10 derniers, j'aurais pensé que vous pouviez retailler le fichier:

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

Le premier est pratique, mais montre trop de sortie. Je ne sais pas pourquoi le second ne fonctionne pas.

Martin Cleaver
la source
Tail n'a pas de "show all lines" d'où mon 100000000
Martin Cleaver
1
tail -n +1 -fà la queue depuis le début.
Stéphane Chazelas
1
La seconde ne fonctionne pas parce que le plus à droite tailne peut rien produire jusqu'à ce qu'il ait vu la dernière ligne de son entrée (comment pourrait-il savoir quelle est la 10ème dernière ligne?) Qui ne se produira tail -fjamais car ne s'arrête jamais.
Stéphane Chazelas
-1

La commande cat -n [filename] | tailobtiendra un décompte et un affichage rapides des enregistrements les plus récents si c'est ce que vous recherchez.

Le -fcommutateur le rend persistant jusqu'à échapper - ce qui ne semble vraiment pas applicable dans votre scénario ou est redondant.

wc -l [filename] obtiendra un nombre de lignes dans la cible

wc -l [filenameprefix]* comptera toutes les lignes de tous les fichiers correspondant au modèle et rapportera même un total récapitulatif à la fin.

Des détails plus complets peuvent produire des réponses plus complètes.

OtisM
la source
-1

C'est l'argument nou --lines(utilisé de manières légèrement différentes, voir ci-dessous):

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

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

Voir aussi l'aide:

$ tail --help
automatix
la source
1
L'OP veut des numéros de ligne, pas un nombre de lignes.
robbat2