Fichero de entrada
Mar 19 06:10:16 ip-172-2-0-53 sendmail[28131]: v2JDA1k4028131: to=root, ctladdr=root (0/0), delay=00:00:15, xdelay=00:00:00, mailer=relay, pri=30580, relay=[127.0.0.1] [127.0.0.1], dsn=2.0.0, stat=Sent (v2JDAG5W028134 Message accepted for delivery)
Mar 19 14:41:26 ip-172-2-0-53 sendmail[29483]: v2JLfNFN029481: to=<[email protected]>,<[email protected]>, delay=00:00:03, xdelay=00:00:03, mailer=esmtp, pri=151738, relay=ifaded-com.mail.p...ction.outlook.com. [xx.xxx.x.x], dsn=2.0.0, stat=Sent (<[email protected]> [InternalId=31288836753166, Hostname=ERGsDGddssdD5.namprd07.prod.outlook.com] 8924 bytes in 0.309, 28.142 KB/sec Queued mail for delivery)
Mar 19 06:10:26 ip-172-2-0-53 sendmail[28131]: v2JDA1k4028131: to=root, ctladdr=root (0/0), delay=00:20:15, xdelay=00:00:00, mailer=relay, pri=30580, relay=[127.0.0.1] [127.0.0.1], dsn=2.0.0, stat=Sent (v2JDAG5W028134 Message accepted for delivery)
He intentado seguir el comando
cat logh.txt | grep -E -o " delay=.[^,]*|^[^ip]+"
Quiero saber los 5 principales tiempos de retraso con fecha. ¿Cómo puedo resolver este problema con el comando llinux? estoy obteniendo el siguiente resultado
Mar 19 06:10:16
delay=00:00:15
Mar 19 14:41:26
delay=00:00:03
Mar 19 06:10:26
delay=00:20:15
Salida deseada
Mar 19 06:10:26 delay=00:20:15
Mar 19 06:10:16 delay=00:00:15
Mar 19 14:41:26 delay=00:00:03
Respuesta1
Necesitará varios pases. Aquí hay una solución que usa sed
, sort
y head
para cut
brindarle los 5 primeros en el orden que desee.
sed -e 's/^\([A-Za-z]\{3\} \{1,2\}[0-9]\{1,2\} \{1,2\}\([0-9]\{2\}:\)\{2\}[0-9]\{2\}\).* \(delay=\([0-9]\{2\}\):\([0-9]\{2\}\):\([0-9]\{2\}\)\).*/\4\5\6 \1 \3/' | sort -nr | head -n5 | cut -d\ -f2-
Con la entrada proporcionada, esto emite:
Mar 19 06:10:26 delay=00:20:15
Mar 19 06:10:16 delay=00:00:15
Mar 19 14:41:26 delay=00:00:03
(Se supone que su entrada está en el formato de registro que proporcionó y que solo incluye líneas con los datos que desea. Puede ser necesario un grep adicional al principio).
que esta haciendo
Analicémoslo.
sed
sed
significa Stream EDITOR. Se utiliza habitualmente para aplicar expresiones regulares a secuencias de texto.
expresión regular de sed
's/^\([A-Za-z]\{3\} \{1,2\}[0-9]\{1,2\} \{1,2\}\([0-9]\{2\}:\)\{2\}[0-9]\{2\}\).* \(delay=\([0-9]\{2\}\):\([0-9]\{2\}\):\([0-9]\{2\}\)\).*/\4\5\6 \1 \3/'
Eso es bastante complicado, pero es necesario que lo sea para evitarretroceso catastrófico.
Estamos usando sustituciones de expresiones regulares. Para ver lo que está haciendo en detalle,prueba Regex101. Por ahora, sepa que se necesita la entrada:
Mar 19 06:10:16 ip-172-2-0-53 sendmail[28131]: v2JDA1k4028131: to=root, ctladdr=root (0/0), delay=00:00:15, xdelay=00:00:00, mailer=relay, pri=30580, relay=[127.0.0.1] [127.0.0.1], dsn=2.0.0, stat=Sent (v2JDAG5W028134 Message accepted for delivery)
Mar 19 14:41:26 ip-172-2-0-53 sendmail[29483]: v2JLfNFN029481: to=<[email protected]>,<[email protected]>, delay=00:00:03, xdelay=00:00:03, mailer=esmtp, pri=151738, relay=ifaded-com.mail.p...ction.outlook.com. [xx.xxx.x.x], dsn=2.0.0, stat=Sent (<[email protected]> [InternalId=31288836753166, Hostname=FOOBAR1.namprd07.prod.outlook.com] 8924 bytes in 0.309, 28.142 KB/sec Queued mail for delivery)
Mar 19 06:10:26 ip-172-2-0-53 sendmail[28131]: v2JDA1k4028131: to=root, ctladdr=root (0/0), delay=00:20:15, xdelay=00:00:00, mailer=relay, pri=30580, relay=[127.0.0.1] [127.0.0.1], dsn=2.0.0, stat=Sent (v2JDAG5W028134 Message accepted for delivery)
y lo convierte en
000015 Mar 19 06:10:16 delay=00:00:15
000003 Mar 19 14:41:26 delay=00:00:03
002015 Mar 19 06:10:26 delay=00:20:15
coincidencia de expresiones regulares sed
^\([A-Za-z]\{3\} \{1,2\}[0-9]\{1,2\} \{1,2\}\([0-9]\{2\}:\)\{2\}[0-9]\{2\}\).* \(delay=\([0-9]\{2\}\):\([0-9]\{2\}\):\([0-9]\{2\}\)\).*
Primero hacemos coincidir explícitamente los componentes de la fecha; los necesitaremos para la salida más adelante. Luego encontramos y relacionamos el retraso y sus componentes de sincronización individualmente; el retraso que deseaba en su salida. Los componentes de sincronización los necesitaremos más adelante para clasificarlos.
sustitución de expresiones regulares de sed
\4\5\6 \1 \3
En el lado de sustitución de la expresión regular, tomamos los componentes de sincronización que tomamos y los concatenamos sin el delimitador ":" que tenían originalmente. Esto es importante, ya que los usaremos más sort
adelante. Después de los componentes de tiempo, agregamos la cadena de fecha y la cadena de retraso original completa; los querremos después de ordenar.
clasificar
sort -nr
Dado que nuestra entrada ahora comienza con un número decimal en lugar de una marca de tiempo, podemos usar sort
el modo numérico, especificado con la -n
bandera.
De forma predeterminada, sort
ordena en orden ascendente, lo que coloca los valores más grandes al final. Dado que esto significaría procesartodode sort
la salida de para encontrar los N valores más grandes, usamos -r
el indicador de clasificación para invertir el orden de salida; ahora, los valores más grandes se generarán primero y podemos hacerlo head
en lugar de `tail.
Nuestro resultado, en este punto, se ve así:
002015 Mar 19 06:10:26 delay=00:20:15
000015 Mar 19 06:10:16 delay=00:00:15
000003 Mar 19 14:41:26 delay=00:00:03
cabeza
head -n5
En este punto, nuestra entrada tendrá primero los valores más grandes y ya sabemos que queremos los 5 valores más grandes. Entonces usamos head
el -n
parámetro para saber head
cuántos valores queremos.
Dado que, en este ejemplo, en realidad no tenemos más de 5 valores, aún obtenemos toda la salida que recibimos.
002015 Mar 19 06:10:26 delay=00:20:15
000015 Mar 19 06:10:16 delay=00:00:15
000003 Mar 19 14:41:26 delay=00:00:03
cortar
cut -d\ -f2-
Como ya no la necesitamos, debemos quitar la clave de clasificación numérica que insertamos sed
en el primer paso. Para ello recurrimos a cut
, que nos permite elegir qué campos queremos de cada fila proporcionada.
Usamos el -d
parámetro de corte para decirle cuál es nuestro separador de campo, nuestro delimitador. Debido a que el separador de campo es un espacio en blanco, debemos escaparlo con \
, lo que nos da -d\
.
Desde cut
la perspectiva de, esto divide la fila 002015 Mar 19 06:10:26 delay=00:20:15
en 002015
Mar
19
06:10:26
delay=00:20:15
.
Para especificar qué campos queremos, usamos -f
. Como queremos todos los campos excepto el primero, usamos -f2-
, lo que nos da el resultado deseado:
Mar 19 06:10:26 delay=00:20:15
Mar 19 06:10:16 delay=00:00:15
Mar 19 14:41:26 delay=00:00:03
Respuesta2
perl -lane '
print join $", /\sdelay=\K(\S+)(?=,)/, splice(@F, 0, 3), /\s\K(delay=\S+)(?=,)/;
' | sort -t: -k 1,1nr -k 2,2nr -k 3,3nr | cut -d\ -f2- | head -n 5