variable see script open logs log kali commands bash text logfiles

bash - script - see logs linux



Dividir el archivo access.log por fechas usando herramientas de lĂ­nea de comandos (7)

Tengo un archivo access.log de Apache, que tiene un tamaño de alrededor de 35 GB. Abordar a través de él ya no es una opción, sin esperar mucho.

Quería dividirlo en muchos archivos pequeños, utilizando la fecha como criterios de división.

La fecha está en formato [15/Oct/2011:12:02:02 +0000] . ¿Alguna idea de cómo podría hacerlo utilizando solo scripts bash, programas de manipulación de texto estándar (grep, awk, sed y likes), canalizaciones y redirección?

El nombre del archivo de entrada es access.log . Me gustaría que los archivos de salida tuvieran un formato como access.apache.15_Oct_2011.log (eso haría el truco, aunque no está bien cuando se ordena).


Aquí hay una versión de awk que genera archivos de registro de orden léxico.

Algunas mejoras de eficiencia: todo hecho en una sola pasada, solo genera fname cuando no es el mismo que antes, cierre fname al cambiar a un nuevo archivo (de lo contrario, podría quedarse sin descriptores de archivos).

awk -F"[]/:[]" '' BEGIN { m2n["Jan"] = 1; m2n["Feb"] = 2; m2n["Mar"] = 3; m2n["Apr"] = 4; m2n["May"] = 5; m2n["Jun"] = 6; m2n["Jul"] = 7; m2n["Aug"] = 8; m2n["Sep"] = 9; m2n["Oct"] = 10; m2n["Nov"] = 11; m2n["Dec"] = 12; } { if($4 != pyear || $3 != pmonth || $2 != pday) { pyear = $4 pmonth = $3 pday = $2 if(fname != "") close(fname) fname = sprintf("access_%04d_%02d_%02d.log", $4, m2n[$3], $2) } print > fname }'' access-log


Bash puro, haciendo un paso a través del registro de acceso:

while read; do [[ $REPLY =~ /[(..)/(...)/(....): ]] d=${BASH_REMATCH[1]} m=${BASH_REMATCH[2]} y=${BASH_REMATCH[3]} #printf -v fname "access.apache.%s_%s_%s.log" ${BASH_REMATCH[@]:1:3} printf -v fname "access.apache.%s_%s_%s.log" $y $m $d echo "$REPLY" >> $fname done < access.log


Combiné las soluciones de Theodore y Thor para usar la mejora de eficiencia de Thor y los archivos diarios, pero conservé el soporte original para direcciones IPv6 en un archivo de formato combinado.

awk '' BEGIN { m2n["Jan"] = 1; m2n["Feb"] = 2; m2n["Mar"] = 3; m2n["Apr"] = 4; m2n["May"] = 5; m2n["Jun"] = 6; m2n["Jul"] = 7; m2n["Aug"] = 8; m2n["Sep"] = 9; m2n["Oct"] = 10; m2n["Nov"] = 11; m2n["Dec"] = 12; } { split($4, a, "[]/:[]") if(a[4] != pyear || a[3] != pmonth || a[2] != pday) { pyear = a[4] pmonth = a[3] pday = a[2] if(fname != "") close(fname) fname = sprintf("access_%04d-%02d-%02d.log", a[4], m2n[a[3]], a[2]) } print >> fname }''


Hice una leve mejora en la respuesta de Theodore para poder ver el progreso al procesar un archivo de registro muy grande.

#!/usr/bin/awk -f BEGIN { split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ", months, " ") for (a = 1; a <= 12; a++) m[months[a]] = a } { split($4, array, "[:/]") year = array[3] month = sprintf("%02d", m[array[2]]) current = year "-" month if (last != current) print current last = current print >> FILENAME "-" year "-" month ".txt" }

También encontré que necesitaba usar gawk ( brew install gawk si no lo tienes) para que esto funcione en Mac OS X.


Perl vino al rescate:

cat access.log | perl -n -e''m@/[(/d{1,2})/(/w{3})/(/d{4}):@; open(LOG, ">>access.apache.$3_$2_$1.log"); print LOG $_;''

Bueno, no es exactamente un programa de manipulación "estándar", pero está hecho para la manipulación de texto.

También he cambiado el orden de los argumentos en el nombre del archivo, para que los archivos se nombren como access.apache.yyyy_mon_dd.log para facilitar la clasificación.


Un poco feo, eso es bash para ti:

for year in 2010 2011 2012; do for month in jan feb mar apr may jun jul aug sep oct nov dec; do for day in 1 2 3 4 5 6 7 8 9 10 ... 31 ; do cat access.log | grep -i $day/$month/$year > $day-$month-$year.log done done done


Una forma de utilizar awk :

awk ''BEGIN { split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ", months, " ") for (a = 1; a <= 12; a++) m[months[a]] = a } { split($4,array,"[:/]"); year = array[3] month = sprintf("%02d", m[array[2]]) print > FILENAME"-"year"_"month".txt" }'' incendiary.ws-2009

Esto dará salida a archivos como:

incendiary.ws-2010-2010_04.txt incendiary.ws-2010-2010_05.txt incendiary.ws-2010-2010_06.txt incendiary.ws-2010-2010_07.txt

Contra un archivo de registro de 150 MB, la respuesta de Chepner tomó 70 segundos en un Core Xeon E31270 de 3.4 GHz 8, mientras que este método tomó 5 segundos.

Inspiración original: " ¿Cómo dividir el archivo de registro de apache existente por mes? "