Por qué los logs importan
Cuando algo falla en un servidor, los logs son el primer lugar donde mirar. Cada servicio deja rastro de lo que hace: a qué hora arrancó, qué peticiones recibió, qué errores tuvo, qué usuarios se conectaron. Saber dónde están y cómo leerlos es una habilidad fundamental para administrar un servidor.
Ubicaciones comunes
Logs del sistema
/var/log/syslog(Debian/Ubuntu) — eventos generales del sistema./var/log/messages(CentOS/Rocky) — equivalente./var/log/kern.log— kernel./var/log/dmesg— mensajes del kernel al arranque./var/log/auth.logo/var/log/secure— autenticación (logins SSH, sudo, etc.)./var/log/boot.log— proceso de arranque.
Servidor web Apache
/var/log/apache2/access.log— todas las peticiones HTTP./var/log/apache2/error.log— errores del servidor.- En CentOS:
/var/log/httpd/access_logy/var/log/httpd/error_log.
Servidor web Nginx
/var/log/nginx/access.log/var/log/nginx/error.log
PHP-FPM
/var/log/php8.2-fpm.log(ajusta la versión)
MySQL / MariaDB
/var/log/mysql/error.log— errores de arranque, crashes, warnings./var/log/mysql/slow.log— queries lentas (si está habilitado).
Correo (Postfix / Exim / Dovecot)
/var/log/mail.logo/var/log/maillog/var/log/dovecot.log
Comandos para trabajar con logs
Leer en tiempo real
tail -f /var/log/nginx/access.log
El clásico. Abre el log y sigue mostrando líneas nuevas conforme llegan. Ideal para diagnosticar un problema reproducible — abres el log en una terminal, reproduces el error en otra, y ves qué aparece.
Últimas N líneas
tail -100 /var/log/syslog
Buscar un patrón
grep "error" /var/log/nginx/error.log grep -i "warning" /var/log/syslog # insensible a mayúsculas grep "404" /var/log/nginx/access.log | wc -l # contar 404s del día
Combinaciones útiles con pipes
# Últimos 500 errores únicos
tail -5000 /var/log/nginx/error.log | grep "error" | sort -u
# IPs que más peticiones hacen
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head
# URLs más visitadas
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head
# Códigos de respuesta agrupados
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
systemd journal
En sistemas modernos (Debian 9+, Ubuntu 16+, CentOS 7+), muchos servicios no escriben a archivos planos sino al journal de systemd. Se consulta con journalctl:
Todos los logs
journalctl
Logs de un servicio específico
journalctl -u nginx journalctl -u mariadb journalctl -u php8.2-fpm
En tiempo real
journalctl -u nginx -f
Desde cierta fecha
journalctl --since "2026-04-15 00:00" --until "2026-04-15 12:00" journalctl --since today journalctl --since "1 hour ago"
Con filtros de prioridad
journalctl -p err # solo errores journalctl -p warning..err # warnings y errores
Entendiendo el formato de access.log
Un log de acceso típico (Nginx/Apache) tiene el formato:
192.0.2.10 - - [15/Apr/2026:10:23:45 +0000] "GET /producto/123 HTTP/1.1" 200 4521 "https://google.com" "Mozilla/5.0..."
Campo por campo:
- 192.0.2.10 — IP del visitante.
- - - — identificadores obsoletos, suelen estar vacíos.
- [15/Apr/2026:10:23:45 +0000] — fecha y hora.
- "GET /producto/123 HTTP/1.1" — método, ruta y versión HTTP.
- 200 — código de respuesta (200 OK, 404 Not Found, 500 Error...).
- 4521 — bytes enviados al cliente.
- "https://google.com" — referrer (desde dónde llegó).
- "Mozilla/5.0..." — user agent (navegador o bot).
Códigos HTTP más importantes
- 2xx — éxito. 200 OK, 201 Created, 204 No Content.
- 3xx — redirecciones. 301 (permanente), 302 (temporal), 304 (no modificado — caché).
- 4xx — error del cliente. 400 malformada, 401 sin auth, 403 prohibido, 404 no existe.
- 5xx — error del servidor. 500 error genérico, 502 bad gateway, 503 sin disponibilidad, 504 timeout.
Muchos 404s suelen ser bots escaneando. Muchos 500s indican problema real — revisa el error.log inmediatamente.
Diagnóstico rápido de problemas comunes
Sitio caído ("502 Bad Gateway")
tail -20 /var/log/nginx/error.log— busca "connect() failed" o "upstream timed out".systemctl status php8.2-fpm— verifica que PHP-FPM está corriendo.tail -50 /var/log/php8.2-fpm.log— errores del proceso PHP.
MySQL no arranca
tail -50 /var/log/mysql/error.log— casi siempre el error exacto está aquí.- Revisa causas típicas: disco lleno (
df -h), my.cnf mal editado, permisos de/var/lib/mysql.
Muchos intentos de login fallido (SSH)
grep "Failed password" /var/log/auth.log | awk '{print $11}' | sort | uniq -c | sort -rn
Lista las IPs con más intentos fallidos. Si hay volúmenes altos, configura fail2ban o bloquéalas en el firewall.
Sitio lento de repente
- Revisa carga del sistema:
uptime,htop. - Busca picos en access.log:
tail -1000 access.log | awk '{print $4}' | sort | uniq -c. - Revisa queries lentas:
tail -100 /var/log/mysql/slow.log.
Rotación de logs con logrotate
Los logs crecen indefinidamente si no se rotan. logrotate ya viene configurado en la mayoría de distribuciones para los servicios comunes. Revisa su configuración en:
/etc/logrotate.d/
Cada archivo es para un servicio. Un ejemplo típico:
/var/log/nginx/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
sharedscripts
postrotate
[ -f /var/run/nginx.pid ] && kill -USR1 $(cat /var/run/nginx.pid)
endscript
}
Qué hace: rota diariamente, guarda 14 versiones, comprime las antiguas, recarga Nginx tras rotar. Si tu log favorito no rota y crece sin límite, añádele un archivo similar en /etc/logrotate.d/.