Introducción
Bienvenido al mundo del procesamiento de texto con AWK. En este laboratorio, aprenderás a utilizar el comando awk para analizar archivos de registro (logs), una tarea común para administradores de sistemas y analistas de datos. AWK es una herramienta potente para procesar datos de texto estructurados en Linux, lo que te permite extraer, filtrar y transformar información de manera eficiente.
Imagina que eres un administrador de sistemas junior encargado de analizar los registros del servidor para identificar posibles amenazas de seguridad y problemas de rendimiento. El comando awk será tu herramienta principal para esta tarea, permitiéndote examinar rápidamente grandes archivos de registro y extraer información valiosa.
Examinar el archivo de registro
Comencemos examinando el contenido de nuestro archivo de registro de muestra. Este archivo contiene registros de acceso al servidor simulados que analizaremos a lo largo de este laboratorio.
Primero, navega al directorio del proyecto:
cd ~/project
Ahora, veamos las primeras líneas del archivo de registro:
head -n 5 server_logs.txt
Deberías ver una salida similar a esta:
2023-08-01 08:15:23 192.168.1.100 GET /index.html 200
2023-08-01 08:16:45 192.168.1.101 GET /about.html 200
2023-08-01 08:17:30 192.168.1.102 POST /login.php 302
2023-08-01 08:18:12 192.168.1.103 GET /products.html 404
2023-08-01 08:19:05 192.168.1.104 GET /services.html 200
Este archivo de registro contiene información sobre las solicitudes al servidor, incluyendo la fecha y hora, la dirección IP, el método HTTP, el recurso solicitado y el código de estado.
Uso básico de AWK: Imprimir campos específicos
Ahora que hemos visto la estructura de nuestro archivo de registro, usemos AWK para extraer información específica. Por defecto, AWK divide cada línea en campos basados en espacios en blanco. Podemos referirnos a estos campos usando $1, $2, etc., donde $1 es el primer campo, $2 es el segundo, y así sucesivamente.
Extraigamos las direcciones IP (el tercer campo) de nuestro archivo de registro:
awk '{print $3}' server_logs.txt | head -n 5
Deberías ver una salida similar a esta:
192.168.1.100
192.168.1.101
192.168.1.102
192.168.1.103
192.168.1.104
En este comando:
awk '{print $3}'le indica a AWK que imprima el tercer campo de cada línea.- Usamos una tubería (
|) para enviar la salida ahead -n 5y limitar la visualización a las primeras 5 líneas.
Ahora, imprimamos tanto la dirección IP como el recurso solicitado:
awk '{print $3, $5}' server_logs.txt | head -n 5
Salida:
192.168.1.100 /index.html
192.168.1.101 /about.html
192.168.1.102 /login.php
192.168.1.103 /products.html
192.168.1.104 /services.html
Aquí, estamos imprimiendo el tercer campo (dirección IP) y el quinto campo (recurso solicitado) para cada línea.
Filtrar entradas de registro
Una de las fortalezas de AWK es su capacidad para filtrar datos basados en condiciones. Usemos esta función para encontrar todas las solicitudes POST en nuestro archivo de registro, ya que podrían ser más sensibles a la seguridad que las solicitudes GET.
Ejecuta el siguiente comando:
awk '$4 == "POST" {print $0}' server_logs.txt
Este comando puede imprimir cientos de líneas porque el archivo de muestra contiene 5,000 entradas de registro. Si solo deseas inspeccionar una muestra manejable mientras aprendes, añade | head -n 10:
awk '$4 == "POST" {print $0}' server_logs.txt | head -n 10
La verificación aún acepta el comando awk simple, así que usa la versión que te ayude a leer la salida más cómodamente.
Analicemos la sintaxis de este comando para entender cómo funciona el filtrado en AWK:
$4 == "POST"- Este es un patrón o condición que AWK evalúa para cada línea:$4se refiere al cuarto campo en la línea actual (en nuestro archivo de registro, este es el método HTTP)==es el operador de igualdad que verifica si dos valores son iguales"POST"es la cadena con la que estamos comparando
{print $0}- Esta es la acción que AWK realiza cuando la condición es verdadera:- Las llaves
{}encierran la acción printes el comando para mostrar texto$0representa toda la línea actual (todos los campos)
- Las llaves
La estructura del comando sigue el patrón de AWK: condición {acción}. AWK lee cada línea y, si la condición se evalúa como verdadera, realiza la acción. Si no se especifica ninguna condición (como en nuestros ejemplos anteriores), la acción se realiza para cada línea.
Deberías ver una salida similar a esta:
2023-08-01 08:17:30 192.168.1.102 POST /login.php 302
2023-08-01 09:23:45 192.168.1.110 POST /submit_form.php 200
2023-08-01 10:45:12 192.168.1.115 POST /upload.php 500
Ahora, busquemos todas las solicitudes que resultaron en un estado 404 (No encontrado):
awk '$6 == "404" {print $1, $2, $5}' server_logs.txt
Este comando sigue el mismo patrón pero con valores diferentes:
- La condición
$6 == "404"verifica si el sexto campo (código de estado) es igual a 404 - La acción
{print $1, $2, $5}imprime solo campos específicos:$1- Primer campo (fecha)$2- Segundo campo (hora)$5- Quinto campo (recurso solicitado)
Esta impresión selectiva te permite concentrarte solo en la información que necesitas.
Salida:
2023-08-01 08:18:12 /products.html
2023-08-01 09:30:18 /nonexistent.html
2023-08-01 11:05:30 /missing_page.html
Puedes combinar múltiples condiciones usando operadores lógicos:
&¶ Y (ambas condiciones deben ser verdaderas)||para O (al menos una condición debe ser verdadera)!para NO (niega una condición)
Por ejemplo, para encontrar todas las solicitudes POST que resultaron en un error (código de estado >= 400):
awk '$4 == "POST" && $6 >= 400 {print $0}' server_logs.txt
Estos filtros pueden ayudarte a identificar rápidamente posibles problemas o actividades sospechosas en los registros de tu servidor.
Contar y resumir datos
AWK es excelente para contar ocurrencias y resumir datos. Usemoslo para contar el número de solicitudes para cada código de estado HTTP.
Ejecuta este comando:
awk '{count[$6]++} END {for (code in count) print code, count[code]}' server_logs.txt | sort -n
Este comando es más complejo, así que analicémoslo paso a paso:
{count[$6]++}- Esta es la acción principal realizada para cada línea:countes un arreglo (arreglo asociativo o diccionario) que estamos creando[$6]usa el valor del sexto campo (código de estado) como índice/clave del arreglo++es el operador de incremento, que suma 1 al valor actual- Por lo tanto, para cada línea, incrementamos el contador para el código de estado específico encontrado
END {for (code in count) print code, count[code]}- Esto se ejecuta después de procesar todas las líneas:ENDes un patrón especial que coincide con el final de la entrada{...}contiene la acción a realizar después de procesar toda la entradafor (code in count)es un bucle que itera a través de todas las claves en el arreglocountprint code, count[code]imprime cada código de estado y su conteo
| sort -n- Envía la salida al comando sort, que ordena numéricamente
Cuando AWK procesa un arreglo como count[$6]++, automáticamente:
- Crea el arreglo si no existe
- Crea un nuevo elemento con valor 0 si la clave no existe
- Luego incrementa el valor en 1
Deberías ver una salida similar a esta:
200 3562
301 45
302 78
304 112
400 23
403 8
404 89
500 15
Este resumen te muestra rápidamente la distribución de los códigos de estado en tu archivo de registro.
Ahora, busquemos los 5 recursos más frecuentemente accedidos:
awk '{count[$5]++} END {for (resource in count) print count[resource], resource}' server_logs.txt | sort -rn | head -n 5
Este comando sigue un patrón similar con algunos cambios:
{count[$5]++}- Cuenta las ocurrencias del quinto campo (el recurso solicitado)END {for (resource in count) print count[resource], resource}- Después de procesar todas las líneas:- Imprime el conteo primero, seguido del recurso
- Este cambio de orden facilita la ordenación numérica por conteo
| sort -rn- Ordena numéricamente en orden inverso (los conteos más altos primero)| head -n 5- Limita la salida a las primeras 5 líneas (los 5 mejores resultados)
Salida:
1823 /index.html
956 /about.html
743 /products.html
512 /services.html
298 /contact.html
Estos comandos de AWK demuestran el poder de usar arreglos para contar y resumir. Puedes adaptar este patrón para contar cualquier campo o combinación de campos en tus datos.
Por ejemplo, para contar el número de solicitudes por dirección IP:
awk '{count[$3]++} END {for (ip in count) print ip, count[ip]}' server_logs.txt
Para contar solicitudes tanto por método como por estado:
awk '{key=$4"-"$6; count[key]++} END {for (k in count) print k, count[k]}' server_logs.txt
Estos resúmenes pueden ayudarte a entender los patrones de tráfico e identificar recursos populares (o problemáticos) en tu servidor.
Crear un informe simple
Para nuestra tarea final, creemos un informe HTML simple que resuma información clave de nuestro archivo de registro. Usaremos un script de AWK almacenado en un archivo separado para esta operación más compleja.
Este paso combina varias ideas de AWK de las secciones anteriores:
- contadores como
total++ - arreglos como
ip_count[$3]++ - un bloque
ENDque imprime el resumen final
Si el script parece largo a primera vista, concéntrate en un bloque a la vez. No necesitas memorizar todo el archivo antes de ejecutarlo.
Primero, crea un archivo llamado log_report.awk con el siguiente contenido:
Consejos: Copia el contenido a continuación y pégalo en tu terminal para crear el archivo.
cat << 'EOF' > log_report.awk
BEGIN {
print "<html><body>"
print "<h1>Server Log Summary</h1>"
total = 0
errors = 0
}
{
total++
if ($6 >= 400) errors++
ip_count[$3]++
resource_count[$5]++
}
END {
print "<p>Total requests: " total "</p>"
print "<p>Error rate: " (errors/total) * 100 "%</p>"
print "<h2>Top 5 IP Addresses</h2>"
print "<ul>"
for (ip in ip_count) {
top_ips[ip] = ip_count[ip]
}
n = asort(top_ips, sorted_ips, "@val_num_desc")
for (i = 1; i <= 5 && i <= n; i++) {
for (ip in ip_count) {
if (ip_count[ip] == sorted_ips[i]) {
print "<li>" ip ": " ip_count[ip] " requests</li>"
break
}
}
}
print "</ul>"
print "<h2>Top 5 Requested Resources</h2>"
print "<ul>"
for (resource in resource_count) {
top_resources[resource] = resource_count[resource]
}
n = asort(top_resources, sorted_resources, "@val_num_desc")
for (i = 1; i <= 5 && i <= n; i++) {
for (resource in resource_count) {
if (resource_count[resource] == sorted_resources[i]) {
print "<li>" resource ": " resource_count[resource] " requests</li>"
break
}
}
}
print "</ul>"
print "</body></html>"
}
EOF
Entendamos este script de AWK sección por sección:
Bloque BEGIN: Se ejecuta antes de procesar cualquier línea de entrada
BEGIN { print "<html><body>" ## Iniciar estructura HTML print "<h1>Server Log Summary</h1>" total = 0 ## Inicializar contador para solicitudes totales errors = 0 ## Inicializar contador para solicitudes con error }Bloque de procesamiento principal: Se ejecuta para cada línea del archivo de entrada
{ total++ ## Incrementar contador de solicitudes totales if ($6 >= 400) errors++ ## Contar respuestas de error (códigos de estado >= 400) ip_count[$3]++ ## Contar solicitudes por dirección IP (campo 3) resource_count[$5]++ ## Contar solicitudes por recurso (campo 5) }Bloque END: Se ejecuta después de procesar todas las líneas de entrada
END { ## Imprimir estadísticas de resumen print "<p>Total requests: " total "</p>" print "<p>Error rate: " (errors/total) * 100 "%</p>" ## Procesar e imprimir las 5 mejores direcciones IP ## ... ## Procesar e imprimir los 5 mejores recursos solicitados ## ... print "</body></html>" ## Finalizar estructura HTML }
Antes de continuar, observa el flujo general:
BEGINimprime las etiquetas HTML de apertura e inicializa los contadores.- El bloque central procesa cada línea de registro y actualiza los totales.
ENDimprime el informe final después de que se haya analizado cada línea.
Examinemos la lógica de ordenación para las mejores IP (la sección de recursos funciona de la misma manera):
## Copiar los conteos a un nuevo arreglo para ordenar
for (ip in ip_count) {
top_ips[ip] = ip_count[ip]
}
## Ordenar el arreglo por valor en orden descendente
n = asort(top_ips, sorted_ips, "@val_num_desc")
## Imprimir las 5 mejores entradas
for (i = 1; i <= 5 && i <= n; i++) {
## Encontrar la IP original que coincide con este conteo
for (ip in ip_count) {
if (ip_count[ip] == sorted_ips[i]) {
print "<li>" ip ": " ip_count[ip] " requests</li>"
break
}
}
}
En este script:
- La función
asort()ordena el arreglo "@val_num_desc"es un argumento especial que le indica que ordene numéricamente por valor en orden descendente- Los bucles anidados encuentran e imprimen las 5 mejores entradas
Puedes pensar en los bucles anidados de esta manera:
- el primer bucle decide qué conteos pertenecen a los 5 mejores
- el segundo bucle encuentra qué dirección IP o recurso produjo cada conteo
Ese patrón de búsqueda es más avanzado que los pasos anteriores, por lo que es normal si esta es la primera parte del laboratorio que se siente como una programación real en lugar de un comando de una sola línea.
Ahora, ejecutemos nuestro script de AWK para generar el informe:
awk -f log_report.awk server_logs.txt > log_report.html
La opción -f le indica a AWK que lea el script del archivo especificado:
-f log_report.awk- Lee el script de AWK del archivolog_report.awkserver_logs.txt- Procesa este archivo usando el script> log_report.html- Redirige la salida al archivolog_report.html
Puedes ver el contenido del informe usando el comando cat:
cat log_report.html
Si la salida HTML parece difícil de escanear en la terminal, previsualiza solo la primera parte primero:
head -n 15 log_report.html
Este informe proporciona un resumen de las solicitudes totales, la tasa de error, las 5 mejores direcciones IP y los 5 mejores recursos solicitados. En un escenario del mundo real, podrías abrir este archivo HTML en un navegador web para obtener una vista formateada.
El enfoque que hemos utilizado en este script demuestra cómo se puede usar AWK para tareas de análisis de datos más complejas. Puedes ampliar este script para incluir estadísticas adicionales o diferentes visualizaciones según tus necesidades específicas.
Resumen
¡Felicidades! Has completado este laboratorio sobre el uso del comando AWK para el análisis de registros. Repasemos lo que has aprendido:
- Uso básico de AWK: Imprimir campos específicos de un archivo de texto estructurado.
- Filtrar datos: Usar condiciones en AWK para seleccionar entradas de registro específicas.
- Contar y resumir: Usar AWK para generar estadísticas a partir de datos de registro.
- Crear informes: Escribir scripts de AWK más complejos para generar informes formateados.
Estas habilidades serán invaluables para analizar archivos de registro, procesar datos y generar informes en tu futuro trabajo como administrador de sistemas o analista de datos.
Aquí hay algunos parámetros y características adicionales de AWK que no cubrimos en este laboratorio:
-F: Especifica un separador de campo distinto al espacio en blanco.-v: Asigna un valor a una variable.NR: Una variable incorporada que representa el número de registro actual.NF: Una variable incorporada que representa el número de campos en el registro actual.- Bloques
BEGINyEND: Patrones especiales para inicialización y finalización. - Funciones incorporadas: Funciones matemáticas, funciones de cadena y más.
Recuerda, la práctica es clave para dominar AWK. Intenta modificar los comandos y scripts de este laboratorio para analizar diferentes aspectos del archivo de registro o para procesar otros tipos de datos de texto estructurados.



