Los logs son la caja negra de tu servidor. Cuando algo falla, los logs tienen la respuesta. Pero si no sabes dónde buscar ni cómo interpretarlos, son inútiles.
Esta guía te enseña a dominar los logs de tu VPS.
Ubicaciones de logs importantes
Logs del sistema
| Archivo | Contenido |
|---|---|
/var/log/syslog | Mensajes generales del sistema |
/var/log/auth.log | Autenticación, SSH, sudo |
/var/log/kern.log | Mensajes del kernel |
/var/log/dmesg | Arranque y hardware |
/var/log/faillog | Intentos de login fallidos |
Logs de servicios web
| Archivo | Contenido |
|---|---|
/var/log/nginx/access.log | Peticiones a Nginx |
/var/log/nginx/error.log | Errores de Nginx |
/var/log/apache2/access.log | Peticiones a Apache |
/var/log/apache2/error.log | Errores de Apache |
Logs de aplicaciones
| Archivo | Contenido |
|---|---|
/var/log/mysql/error.log | Errores de MySQL |
/var/log/php8.2-fpm.log | Errores de PHP-FPM |
/var/log/redis/redis-server.log | Logs de Redis |
/var/log/postgresql/ | Logs de PostgreSQL |
Logs de seguridad
| Archivo | Contenido |
|---|---|
/var/log/auth.log | SSH, sudo, login |
/var/log/fail2ban.log | Bans de Fail2Ban |
/var/log/ufw.log | Firewall UFW |
Comandos esenciales
Ver logs en tiempo real
# Seguir un archivo
tail -f /var/log/syslog
# Seguir múltiples archivos
tail -f /var/log/nginx/*.log
# Con colores (requiere ccze)
tail -f /var/log/syslog | ccze -A
Buscar en logs
# Buscar texto
grep "error" /var/log/syslog
# Ignorar mayúsculas/minúsculas
grep -i "error" /var/log/syslog
# Con contexto (3 líneas antes y después)
grep -C 3 "error" /var/log/syslog
# Buscar en múltiples archivos
grep -r "error" /var/log/nginx/
# Invertir búsqueda (excluir)
grep -v "GET /health" /var/log/nginx/access.log
Filtrar por fecha
# Logs de hoy
grep "$(date '+%b %d')" /var/log/syslog
# Logs de ayer
grep "$(date -d 'yesterday' '+%b %d')" /var/log/syslog
# Rango de tiempo con awk
awk '/Feb 9 10:00/,/Feb 9 11:00/' /var/log/syslog
Contar ocurrencias
# Contar errores
grep -c "error" /var/log/syslog
# Top 10 IPs en access.log
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
# Top 10 URLs más visitadas
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
# Códigos de respuesta
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
Journalctl: El poder de systemd
Comandos básicos
# Ver todos los logs
journalctl
# Logs del sistema actual (desde último boot)
journalctl -b
# Logs del boot anterior
journalctl -b -1
# Seguir en tiempo real
journalctl -f
Filtrar por servicio
# Logs de Nginx
journalctl -u nginx
# Logs de MySQL
journalctl -u mysql
# Logs de PHP-FPM
journalctl -u php8.2-fpm
# Múltiples servicios
journalctl -u nginx -u php8.2-fpm
Filtrar por prioridad
# Solo errores y superiores
journalctl -p err
# Solo críticos
journalctl -p crit
# Niveles: emerg, alert, crit, err, warning, notice, info, debug
journalctl -p warning
Filtrar por tiempo
# Última hora
journalctl --since "1 hour ago"
# Hoy
journalctl --since today
# Ayer
journalctl --since yesterday --until today
# Rango específico
journalctl --since "2026-02-09 10:00" --until "2026-02-09 12:00"
# Últimos 100 mensajes
journalctl -n 100
Formato de salida
# Sin paginador
journalctl --no-pager
# JSON (para procesar)
journalctl -o json
# JSON legible
journalctl -o json-pretty
# Solo mensajes (sin metadata)
journalctl -o cat
Análisis de logs de Nginx
Access log formato
IP - - [fecha] "método URL protocolo" código tamaño "referer" "user-agent"
Análisis útiles
# Peticiones por código de respuesta
awk '{print $9}' access.log | sort | uniq -c | sort -rn
# 404s (páginas no encontradas)
grep '" 404 ' access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -20
# 500s (errores de servidor)
grep '" 500 ' access.log | tail -20
# Peticiones por hora
awk '{print $4}' access.log | cut -d: -f1,2 | uniq -c
# Ancho de banda por IP
awk '{sum[$1] += $10} END {for (ip in sum) print sum[ip], ip}' access.log | sort -rn | head -10
# Bots y crawlers
grep -i "bot\|crawler\|spider" access.log | awk '{print $1}' | sort | uniq -c | sort -rn
Detectar ataques
# IPs con más de 1000 peticiones
awk '{print $1}' access.log | sort | uniq -c | sort -rn | awk '$1 > 1000'
# Intentos de acceso a archivos sospechosos
grep -E "\.(php|asp|aspx|jsp|cgi)$" access.log | grep -v "index.php"
# Intentos de SQL injection
grep -E "(select|union|insert|delete|update|drop)" access.log
# Intentos de path traversal
grep "\.\.\/" access.log
Análisis de logs de errores
Nginx error.log
# Últimos errores
tail -50 /var/log/nginx/error.log
# Errores críticos
grep -E "\[crit\]|\[emerg\]|\[alert\]" /var/log/nginx/error.log
# Errores de upstream (PHP-FPM)
grep "upstream" /var/log/nginx/error.log
# Conexiones rechazadas
grep "Connection refused" /var/log/nginx/error.log
PHP-FPM logs
# Errores de PHP
grep -E "Fatal|Error|Warning" /var/log/php8.2-fpm.log
# Slow requests (si está habilitado)
grep "slow" /var/log/php8.2-fpm.log
# Pool errors
grep "pool" /var/log/php8.2-fpm.log
MySQL error.log
# Errores recientes
tail -100 /var/log/mysql/error.log
# Queries abortadas
grep "Aborted" /var/log/mysql/error.log
# Errores de conexión
grep -i "connection" /var/log/mysql/error.log
# Warnings
grep "Warning" /var/log/mysql/error.log
Rotación de logs con logrotate
Configuración por defecto
# Configuración global
cat /etc/logrotate.conf
# Configuraciones específicas
ls /etc/logrotate.d/
Configuración personalizada
# /etc/logrotate.d/mi-app
/var/www/mi-app/logs/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 0640 www-data www-data
sharedscripts
postrotate
systemctl reload nginx > /dev/null 2>&1 || true
endscript
}
Opciones comunes
| Opción | Significado |
|---|---|
daily/weekly/monthly | Frecuencia de rotación |
rotate 7 | Mantener 7 archivos |
compress | Comprimir logs antiguos |
delaycompress | Comprimir en la siguiente rotación |
missingok | No error si falta el archivo |
notifempty | No rotar si está vacío |
copytruncate | Copiar y truncar (para apps que no reabren) |
Probar configuración
# Probar sin ejecutar
logrotate -d /etc/logrotate.d/mi-app
# Forzar rotación
logrotate -f /etc/logrotate.d/mi-app
Scripts de análisis útiles
Resumen diario de logs
#!/bin/bash
# /root/scripts/daily-log-report.sh
echo "========== RESUMEN DE LOGS $(date '+%Y-%m-%d') =========="
echo ""
echo "=== ERRORES DEL SISTEMA ==="
journalctl -p err --since yesterday --until today --no-pager | tail -20
echo ""
echo "=== TOP 10 IPs (Nginx) ==="
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
echo ""
echo "=== CÓDIGOS DE RESPUESTA ==="
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
echo ""
echo "=== INTENTOS SSH FALLIDOS ==="
grep "Failed password" /var/log/auth.log | wc -l
echo ""
echo "=== BANS DE FAIL2BAN ==="
grep "Ban" /var/log/fail2ban.log | tail -10
echo ""
echo "=== ESPACIO EN LOGS ==="
du -sh /var/log/*/ 2>/dev/null | sort -rh | head -10
Monitor de errores en tiempo real
#!/bin/bash
# /root/scripts/error-monitor.sh
# Monitorear múltiples logs por errores
tail -f /var/log/nginx/error.log \
/var/log/php8.2-fpm.log \
/var/log/mysql/error.log 2>/dev/null | \
grep --line-buffered -i "error\|fatal\|crit"
Alerta por errores excesivos
#!/bin/bash
# /root/scripts/check-errors.sh
THRESHOLD=50
ERRORS=$(journalctl -p err --since "5 minutes ago" --no-pager | wc -l)
if [ $ERRORS -gt $THRESHOLD ]; then
echo "$ERRORS errores en los últimos 5 minutos" | \
mail -s "ALERTA: Errores excesivos en VPS" [email protected]
fi
Centralización de logs
Enviar logs a servidor remoto
# /etc/rsyslog.d/remote.conf
*.* @logserver.tudominio.com:514 # UDP
*.* @@logserver.tudominio.com:514 # TCP
# Reiniciar
systemctl restart rsyslog
Loki + Grafana (Docker)
# docker-compose.yml
version: '3.8'
services:
loki:
image: grafana/loki:latest
ports:
- "3100:3100"
volumes:
- loki-data:/loki
promtail:
image: grafana/promtail:latest
volumes:
- /var/log:/var/log:ro
- ./promtail-config.yml:/etc/promtail/config.yml
command: -config.file=/etc/promtail/config.yml
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
volumes:
- grafana-data:/var/lib/grafana
volumes:
loki-data:
grafana-data:
Limpieza de logs
Limpiar manualmente
# Vaciar log sin eliminar archivo
> /var/log/nginx/access.log
# Truncar a últimas 1000 líneas
tail -1000 /var/log/syslog > /var/log/syslog.tmp && mv /var/log/syslog.tmp /var/log/syslog
# Eliminar logs antiguos de journald
journalctl --vacuum-time=7d # Mantener 7 días
journalctl --vacuum-size=500M # Mantener 500MB
Configurar límite de journald
# /etc/systemd/journald.conf
[Journal]
SystemMaxUse=500M
SystemMaxFileSize=50M
MaxRetentionSec=1week
systemctl restart systemd-journald
Preguntas frecuentes
¿Dónde están los logs si mi aplicación falla?
Empieza con journalctl -u nombre-servicio para servicios systemd. Para apps web, revisa /var/log/nginx/error.log o el log específico de tu framework.
¿Cuánto espacio deben ocupar los logs?
Depende del tráfico, pero típicamente 500MB-2GB es razonable. Si ocupan más, configura mejor logrotate o reduce el nivel de logging.
¿Cómo encuentro quién está atacando mi servidor?
Revisa /var/log/auth.log para SSH y /var/log/nginx/access.log para web. Busca IPs con muchas peticiones o intentos fallidos.
¿Debo mantener logs antiguos?
Para cumplimiento legal o debugging, mantén 30-90 días. Comprímelos con logrotate. Archiva logs críticos en almacenamiento externo.
¿journalctl o archivos de log tradicionales?
journalctl para servicios systemd y logs del sistema. Archivos tradicionales para apps específicas. Ambos tienen su uso.
Nuestra recomendación
Para el día a día:
journalctl -fpara logs en tiempo realgreppara buscar errores específicos- Script de resumen diario
Para producción:
- Logrotate bien configurado
- Alertas por errores excesivos
- Centralización si tienes múltiples VPS
¿Necesitas gestión profesional de logs? La administración gestionada de Avantys incluye análisis y alertas de logs.
Conclusión
Los logs son tu mejor amigo cuando algo falla. Domina journalctl, configura rotación adecuada, y crea scripts de análisis que te ahorren tiempo.
No esperes a tener un problema para aprender a leer logs.
¿Necesitas un VPS con logging avanzado? Explora los VPS de Avantys con monitorización incluida.
¿Quieres que lo hagamos por ti?
En Avantys gestionamos tu web, hosting y crecimiento digital de punta a punta. Tú a lo importante.