cola -f, pero con números de línea


21

Estoy tratando de ver cuántas veces foo baraparece /var/log/foo.logdentro de un tiempo arbitrario en un servidor remoto, pero nada de lo que he intentado hasta ahora ha funcionado.

Ya tengo un script de temporizador que uso para hacer un seguimiento de cuánto tiempo ha pasado desde que comencé a seguir /var/log/foo.log, y ahora me gustaría una forma de saber cuántas veces foo barha aparecido en la salida de cola.

Busqué en google, pero no encontré nada pertinente en las primeras 10 páginas de resultados.

Esto es lo que he probado con resultados frustrantes:

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

Incluso intenté escribir una secuencia de comandos sed que actuara como tail -f, pero logré un avance limitado o nulo con eso.

NOTA

el servidor remoto ejecuta una versión anterior de coreutils, y la actualización es una opción, pero NO es de ninguna manera la solución deseada.


2
¿De qué manera no funciona? Prueba la --line-bufferedopción de grep. Otail -f ... | awk '/foo bar/{print ++n, $0}'
Stéphane Chazelas

¿Por qué no funciona en control remoto? Ejemplo:tail -f /var/log/log.log | awk '{ printf "[%d]> %s\n", NR+1 ,$0; fflush(stdout); }'

Respuestas:


29
tail -f | nl

funciona para mí y es lo primero en lo que pensé, es decir, si realmente quieres que las líneas estén numeradas del 1 y no con el número de línea real del archivo visto. Opcionalmente agregue grepsi es necesario al lugar apropiado (antes o después nl). Sin embargo, recuerde que puede ocurrir el almacenamiento en búfer. En mi caso particular, greptiene la --line-bufferedopción, pero nlamortigua su salida y no tiene una opción para desactivarla. Por lo tanto, el tail | nl | grepcombo realmente no fluye bien.

Dicho eso

tail -f | grep -n pattern

A mí también me funciona. La numeración comienza nuevamente desde el comienzo de la "recopilación" en lugar del comienzo de todo el archivo de registro.


La versión de grep que se ejecuta en el servidor no tiene una -nopción.
Alexej Magura

Sin embargo, tiene la opción larga --line-number: tail -f /var/log/foo.log | grep foo\ bar --line-number¡funciona!
Alexej Magura

1
Eso es interesante: no he comprobado POSIX como tal, pero la página de manual de GNU grep dice: -n está especificado por POSIX .
Peter

16

Creo que esto es mejor..

less -N +F <filepath>

2
¿Podría explicar por qué cree que es mejor?
Navigatron

Esta es una gran edición, estoy volviendo.
Adam Eberlin

3
Muestra el número de línea tomando como referencia todo el archivo. cola -f | nl muestra el número de línea tomando como referencia la primera salida de tail.
rafaelvalle

Esto es muy útil y aborda el título del OP, pero no su pregunta . Querían saber cuántas veces aparece X en un archivo: P
Timmah

6

También puede canalizar la salida a less, tiene una función de número de línea, -Nque le permitiría desplazarse hacia adelante y hacia atrás a través del registro.

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

Ejemplo

  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/

NOTA: tome nota de la salida. Puede que le guste o no esta característica, pero tomará largas líneas y las cortará para que continúen en la siguiente línea, pero aún así mantengan el mismo número de línea correspondiente. ¡Encuentro esta característica invaluable al analizar archivos de registro que son anchos! Puede ver el efecto de esta función en las líneas 6 y 8 .


Esto no está claro. ¿Dónde se especifica el nombre del archivo? Debe aclararse, señalando que la salida está numerada desde 1 comenzando con las últimas 10 líneas del nombre de archivo, ya que ese es el comportamiento predeterminado de tail. En cuanto a las líneas largas, ese comportamiento se alterna dentro del lessuso -S.
ILMostro_7

2

Para agrupar nuevas líneas solo en el archivo de registro, ya que vienen con su número de línea, puede hacer lo siguiente:

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

(con mawk, querrás agregar la -Winteractiveopción para evitar el almacenamiento en búfer de entrada (!)).

wc -llee las líneas que ya estaban allí y las cuenta (los caracteres de la nueva línea, lo que significa que aún funciona, incluso si la última línea aún no está llena), y luego tail -fel resto (comenzando desde donde wcdejó de leer) y decimos awkcuál es el número de línea de El primero que ve.


elegir lcomo el nombre de la variable me hizo entrecerrar los ojos en $ l, pensando que era $1^^ (pero como sé (y 100% de confianza) en ti, volví a leer y vi la verdad). Solo por curiosidad: para evitar alguna "condición de carrera" entre el wc -ly el tail -f(si el archivo crece rápido, uno puede descartar algunas líneas y, por lo tanto, el NR comienza desde el número incorrecto), ¿es posible omitir $llíneas en su lugar? (¿y qué límite hay para la cola -nen posix y en gnu?). Tal vez con un archivo intermedio temporal?
Olivier Dulac

@OlivierDulac, tail -n +1(lea cualquier cosa desde la posición de inicio) aborda las preocupaciones de la condición de carrera. Leerá las líneas que no estaban en el archivo en el momento wc -lfinalizado, desde la posición exacta a la wcizquierda. Por lo tanto, NR tendrá la posición correcta independientemente de cuántas líneas se hayan escrito entre el wcfinal y el tailinicio. Si tuviera que tailcomenzar desde una posición relativa al final del archivo, tendría problemas.
Stéphane Chazelas

oh, interesante: de hecho, los datos se acumulan en stdin mientras nada los lee (entre el final del wc hasta el comienzo de la cabeza) ... Debería haberme dado cuenta de eso. Gracias. Ahora veo por qué "<archivo". inteligente, como siempre :)
Olivier Dulac

1
@OlivierDulac, sobre las limitaciones (que no se aplican tail -n +1aquí), para los archivos normales, la mayoría de las implementaciones no tienen una, ya que pueden comenzar desde el final y seekvolver hasta encontrar la enésima nueva línea sin tener que almacenar más de un valor de buf de datos en la memoria. Para la entrada no buscable, ahí es donde puede toparse con límites. POSIX requiere implementaciones para poder almacenar al menos 10 x LINE_MAX bytes (LINE_MAX es al menos 2048). La cola de GNU no tiene otro límite que la memoria AFAIK
Stéphane Chazelas

0

Si quisiera numerar desde el principio, necesitaría grep -n para aplicar a todas las líneas.

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

Si solo quisiera mostrar los últimos 10, hubiera pensado que podría volver a ajustar el archivo:

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

El primero es útil, pero muestra demasiada salida. No sé por qué el segundo no funciona.


La cola no tiene un "mostrar todas las líneas", por lo tanto, mi 100000000
Martin Cleaver

1
tail -n +1 -fa la cola desde el principio.
Stéphane Chazelas

1
El segundo no funciona porque el extremo derecho tailno puede generar nada hasta que haya visto la última línea de su entrada (¿cómo sabría cuál es la décima última línea?), Que nunca sucederá, ya que tail -fnunca se detiene.
Stéphane Chazelas

-1

El comando cat -n [filename] | tailobtendrá un recuento rápido y una visualización de los registros más recientes si eso es lo que está buscando.

El -finterruptor lo hace persistente hasta el escape, lo que realmente no parece aplicable en su escenario o es redundante.

wc -l [filename] obtendrá un recuento de las líneas en el objetivo

wc -l [filenameprefix]* contará todas las líneas en todos los archivos que coincidan con el patrón e incluso informará un resumen total al final.

Un detalle más completo puede dar respuestas más completas.


-1

Es el argumento no --lines(usado de maneras ligeramente diferentes, ver abajo):

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

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

Ver también la ayuda:

$ tail --help

1
El OP quiere números de línea, no un número de líneas.
robbat2
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.