Volver al índice
root@vps-donweb:~/docs/logs$

Logs del Sistema

herramienta journalctl · syslog
SO Ubuntu 22.04 LTS
categoría Sistema
MAPA Dónde está cada log en Ubuntu
/var/log/
├── syslog          # log general del sistema (el más importante)
├── auth.log        # autenticación SSH, sudo, PAM
├── kern.log        # mensajes del kernel
├── dmesg           # mensajes de arranque del kernel
├── dpkg.log        # instalaciones y actualizaciones de paquetes
├── apt/
│   ├── history.log  # historial de apt
│   └── term.log     # output de instalaciones
├── nginx/
│   ├── access.log   # peticiones HTTP
│   └── error.log    # errores de Nginx
├── mysql/
│   └── error.log    # errores de MariaDB
├── fail2ban.log    # bans y actividad de Fail2ban
├── ufw.log         # actividad del firewall UFW
├── cron.log        # ejecuciones de cron (en algunas distros)
└── mail.log        # actividad del servidor de email

En Ubuntu 22.04 con systemd, muchos servicios escriben solo en journald (no en archivos). Usá journalctl para verlos.

TAIL / CAT Leer logs en tiempo real y estáticos
# Seguir log en tiempo real
tail -f /var/log/syslog
tail -f /var/log/nginx/error.log
tail -f /var/log/auth.log

# Ver las últimas N líneas
tail -100 /var/log/syslog
tail -50  /var/log/nginx/access.log

# Seguir múltiples logs a la vez
tail -f /var/log/nginx/access.log \
         /var/log/nginx/error.log

# Ver desde el principio
head -50 /var/log/syslog
cat /var/log/dpkg.log

# Ver log comprimido (rotado)
zcat /var/log/syslog.1.gz
zcat /var/log/nginx/access.log.2.gz | tail -100

# Ver todos los logs rotados de un servicio
ls -lh /var/log/nginx/
zcat /var/log/nginx/access.log*.gz | wc -l
JOURNALCTL El comando central de logs en systemd
# Ver todos los logs del sistema (más recientes al final)
journalctl

# Seguir en tiempo real (como tail -f)
journalctl -f

# Ver solo los errores y superiores
journalctl -p err
journalctl -p warning

# Niveles de prioridad disponibles:
#  emerg(0) alert(1) crit(2) err(3)
#  warning(4) notice(5) info(6) debug(7)

# Últimas N líneas
journalctl -n 100
journalctl -n 50 -f    # últimas 50 y seguir

# Sin paginación (output directo)
journalctl --no-pager
journalctl --no-pager -n 50

# Output en formato corto, con timestamps
journalctl -o short-precise

# Output en JSON (para scripts)
journalctl -o json-pretty -n 5
FILTROS Filtrar por servicio, tiempo y boot
# Por unidad de systemd (servicio)
journalctl -u nginx
journalctl -u nginx -f
journalctl -u nginx -u php8.2-fpm   # múltiples servicios

# Por rango de tiempo
journalctl --since "2024-05-28 00:00:00"
journalctl --since "1 hour ago"
journalctl --since "yesterday"
journalctl --since today
journalctl --since "2024-05-01" --until "2024-05-31"

# Por boot del sistema
journalctl -b          # boot actual
journalctl -b -1        # boot anterior
journalctl -b -2        # antepenúltimo
journalctl --list-boots # listar todos los boots

# Por proceso o PID
journalctl _PID=1234
journalctl _COMM=nginx

# Combinando filtros
journalctl -u nginx -p err --since "1 hour ago"
GESTIÓN Administrar el espacio de journald
# Ver cuánto espacio ocupa el journal
journalctl --disk-usage

# Eliminar logs viejos por tamaño
journalctl --vacuum-size=500M

# Eliminar logs más viejos que N días
journalctl --vacuum-time=30d
journalctl --vacuum-time=7d

# Configurar límite permanente de tamaño
# /etc/systemd/journald.conf
[Journal]
SystemMaxUse=500M
SystemKeepFree=1G
MaxRetentionSec=30day
Compress=yes

# Aplicar cambios
systemctl restart systemd-journald

En un VPS con poco disco, limitar journald a 500MB evita que los logs consuman todo el espacio con el tiempo.

GREP Buscar y filtrar en logs
# Buscar texto en log
grep "error" /var/log/nginx/error.log
grep -i "error" /var/log/syslog       # insensible a mayúsculas

# Buscar y mostrar contexto (líneas antes/después)
grep -A 3 -B 3 "critical" /var/log/syslog

# Excluir líneas
grep -v "GET /favicon" /var/log/nginx/access.log

# Múltiples patrones
grep -E "error|warning|critical" /var/log/syslog

# Buscar en múltiples archivos
grep "Failed password" /var/log/auth.log*

# Contar ocurrencias
grep -c "404" /var/log/nginx/access.log

# Solo mostrar la parte que coincide
grep -o "\"GET.*HTTP" /var/log/nginx/access.log | head -20

# Buscar en logs comprimidos
zgrep "error" /var/log/nginx/error.log.*.gz
AWK / SED Extraer y procesar campos
# Formato de access.log de Nginx:
# IP - - [fecha] "método ruta protocolo" status bytes "referer" "agente"

# Extraer solo las IPs
awk '{print $1}' /var/log/nginx/access.log

# IPs más frecuentes
awk '{print $1}' /var/log/nginx/access.log \
  | sort | uniq -c | sort -rn | head -20

# Rutas más solicitadas
awk '{print $7}' /var/log/nginx/access.log \
  | sort | uniq -c | sort -rn | head -20

# Códigos de estado y su frecuencia
awk '{print $9}' /var/log/nginx/access.log \
  | sort | uniq -c | sort -rn

# Solo errores 4xx y 5xx
awk '$9 ~ /^[45]/' /var/log/nginx/access.log

# IPs con más errores 404
awk '$9==404{print $1}' /var/log/nginx/access.log \
  | sort | uniq -c | sort -rn | head -10

# Total de bytes transferidos
awk '{sum+=$10} END {print sum/1024/1024 " MB"}' \
  /var/log/nginx/access.log

# Tráfico por hora
awk '{print $4}' /var/log/nginx/access.log \
  | cut -d: -f2 | sort | uniq -c
GOACCCESS Análisis visual de logs de Nginx

GoAccess es un analizador de logs en tiempo real con interfaz en terminal o exportación a HTML.

# Instalar
apt install goaccess

# Análisis interactivo en terminal
goaccess /var/log/nginx/access.log \
  --log-format=COMBINED

# Generar reporte HTML estático
goaccess /var/log/nginx/access.log \
  --log-format=COMBINED \
  -o /var/www/html/report.html

# Análisis en tiempo real (se actualiza solo)
tail -f /var/log/nginx/access.log \
  | goaccess --log-format=COMBINED -

# Analizar logs comprimidos también
zcat /var/log/nginx/access.log.*.gz \
  | cat - /var/log/nginx/access.log \
  | goaccess --log-format=COMBINED -

El reporte HTML de GoAccess muestra gráficas de visitas, IPs, rutas, códigos de estado y agentes de usuario — muy útil para entender el tráfico del servidor.

SEGURIDAD Analizar logs de autenticación
# Ver intentos fallidos de SSH
grep "Failed password" /var/log/auth.log | tail -30

# IPs con más intentos fallidos
grep "Failed password" /var/log/auth.log \
  | awk '{print $11}' \
  | sort | uniq -c | sort -rn | head -15

# Usuarios que intentaron loguearse
grep "Failed password" /var/log/auth.log \
  | awk '{print $9}' \
  | sort | uniq -c | sort -rn | head -10

# Logins exitosos
grep "Accepted publickey" /var/log/auth.log
grep "Accepted password"  /var/log/auth.log

# Actividad de sudo
grep "sudo" /var/log/auth.log | grep "COMMAND"

# Actividad de Fail2ban
grep "Ban\|Unban" /var/log/fail2ban.log | tail -30

# Últimas conexiones
last -20
lastb -20   # intentos fallidos
LOGROTATE Rotación automática de logs

Logrotate evita que los logs crezcan indefinidamente. Comprime, archiva y elimina logs viejos automáticamente. Se ejecuta vía cron o systemd.

# Configuración global
/etc/logrotate.conf

# Configuraciones por servicio (sobreescriben la global)
/etc/logrotate.d/nginx
/etc/logrotate.d/mysql
/etc/logrotate.d/mi-app

# Ver configuración de un servicio
cat /etc/logrotate.d/nginx
CONFIG Crear configuración de rotación propia
# /etc/logrotate.d/mi-app
/var/log/mi-app/*.log {
    daily                   # rotar cada día
    missingok               # no error si no existe
    rotate 14               # mantener 14 versiones
    compress                # comprimir con gzip
    delaycompress           # comprimir recién en la siguiente rotación
    notifempty              # no rotar si está vacío
    create 640 www-data adm  # crear nuevo archivo con estos permisos
    sharedscripts           # ejecutar postrotate una sola vez
    postrotate
        # Reabrir archivos de log en Nginx
        [ -f /run/nginx.pid ] && kill -USR1 $(cat /run/nginx.pid)
    endscript
}

# Otras opciones útiles:
# weekly         → rotar cada semana
# monthly        → rotar cada mes
# size 100M      → rotar cuando supere 100MB
# maxage 30      → eliminar logs de más de 30 días
# dateext        → agregar fecha en el nombre del archivo rotado
# Probar configuración sin ejecutar
logrotate -d /etc/logrotate.d/mi-app

# Forzar rotación manual
logrotate -f /etc/logrotate.d/mi-app

# Ejecutar rotación global ahora
logrotate /etc/logrotate.conf

# Ver estado de la última rotación
cat /var/lib/logrotate/status
NGINX Logs de Nginx
# Accesos en tiempo real
tail -f /var/log/nginx/access.log

# Solo errores
tail -f /var/log/nginx/error.log

# Errores críticos del día
grep "$(date +%Y/%m/%d)" /var/log/nginx/error.log \
  | grep -E "emerg|alert|crit|error"

# Cambiar nivel de log en nginx.conf
# error_log /var/log/nginx/error.log warn;
# Niveles: debug info notice warn error crit alert emerg

# Formato personalizado de access log
log_format detailed '$remote_addr - $remote_user [$time_local] '
                      '"$request" $status $body_bytes_sent '
                      '"$http_referer" "$http_user_agent" '
                      '$request_time $upstream_response_time';
access_log /var/log/nginx/access.log detailed;
MARIADB Logs de MariaDB
# Log de errores
tail -f /var/log/mysql/error.log
journalctl -u mariadb -f

# Habilitar slow query log (en /etc/mysql/mariadb.conf.d/50-server.cnf)
slow_query_log      = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time     = 2         # queries de más de 2 segundos
log_queries_not_using_indexes = 1

# Ver slow queries
tail -f /var/log/mysql/slow.log

# Analizar slow queries con mysqldumpslow
mysqldumpslow -s t /var/log/mysql/slow.log | head -20

# Habilitar general log (CUIDADO: muy verboso, solo para debug)
mysql -u root -p -e "SET GLOBAL general_log = 'ON';"
mysql -u root -p -e "SET GLOBAL general_log = 'OFF';"
SISTEMA Logs del sistema operativo
# Mensajes de arranque del kernel
dmesg
dmesg | tail -30
dmesg | grep -i error
dmesg -T   # con timestamps legibles

# Log de instalaciones de paquetes
cat /var/log/dpkg.log | grep "install"
cat /var/log/apt/history.log

# Log del sistema general
tail -f /var/log/syslog
grep "OOM\|out of memory" /var/log/syslog   # detectar falta de RAM
grep "disk\|I/O error" /var/log/syslog       # errores de disco

# Errores críticos del sistema hoy
journalctl -p err --since today --no-pager

# Últimos reinicios del sistema
journalctl --list-boots
last reboot | head -10
DOCKER Logs de contenedores
# Logs de un contenedor
docker logs mi-app
docker logs -f mi-app              # en tiempo real
docker logs --tail 100 mi-app
docker logs --since 1h mi-app      # última hora
docker logs --timestamps mi-app

# Logs con Docker Compose
docker compose logs -f
docker compose logs -f app         # servicio específico
docker compose logs --tail 50 db

# Ver dónde guarda los logs Docker
docker inspect mi-app \
  | grep LogPath

# Configurar límite de tamaño de logs en docker-compose.yml
logging:
  driver: json-file
  options:
    max-size: "50m"
    max-file: "5"

# Enviar logs de Docker a journald
logging:
  driver: journald

Sin límite de tamaño, los logs de Docker en /var/lib/docker/containers/ pueden llenar el disco. Configurar siempre max-size.

RECURSOS Monitorear el sistema en tiempo real
# Procesos y uso de CPU/RAM
top
htop         # versión mejorada (apt install htop)

# Uso de disco
df -h                               # espacio por partición
du -sh /var/www/*                   # tamaño por sitio
du -sh /var/log/*  | sort -rh       # logs más grandes
du -sh /* 2>/dev/null | sort -rh | head -15

# I/O de disco en tiempo real
iostat -x 1                         # apt install sysstat
iotop                                # apt install iotop

# Red
nethogs                              # uso de red por proceso
iftop                                # tráfico por conexión
ss -tulnp                            # puertos escuchando
ss -tnp state established           # conexiones activas

# RAM
free -h
vmstat 1 10   # cada 1s durante 10 iteraciones

# Todo en uno — resumen del sistema
watch -n 2 'df -h && echo "---" && free -h && echo "---" && uptime'
ALERTAS Script de monitoreo con alertas por email
#!/bin/bash
# /usr/local/bin/monitor-vps.sh
# Verificar recursos críticos y alertar si superan umbral

EMAIL="tu@email.com"
HOSTNAME=$(hostname)
ALERTA=0
MENSAJE=""

# Disco — alertar si alguna partición supera 85%
while read -r linea; do
  USO=$(echo "$linea" | awk '{print $5}' | tr -d '%')
  MOUNT=$(echo "$linea" | awk '{print $6}')
  if [ "$USO" -gt 85 ] 2>/dev/null; then
    MENSAJE+="⚠ DISCO $MOUNT al ${USO}%\n"
    ALERTA=1
  fi
done < <(df -h | tail -n +2)

# RAM — alertar si uso supera 90%
RAM_TOTAL=$(free | awk '/Mem:/{print $2}')
RAM_USADA=$(free | awk '/Mem:/{print $3}')
RAM_PCT=$(( RAM_USADA * 100 / RAM_TOTAL ))
if [ "$RAM_PCT" -gt 90 ]; then
  MENSAJE+="⚠ RAM al ${RAM_PCT}%\n"
  ALERTA=1
fi

# Servicios críticos
for SVC in nginx mariadb; do
  if ! systemctl is-active --quiet "$SVC"; then
    MENSAJE+="🔴 SERVICIO CAÍDO: $SVC\n"
    ALERTA=1
  fi
done

# Enviar alerta si hay problemas
if [ "$ALERTA" -eq 1 ]; then
  echo -e "$MENSAJE" \
    | mail -s "⚠ Alerta VPS $HOSTNAME" "$EMAIL"
fi
chmod +x /usr/local/bin/monitor-vps.sh

# Ejecutar cada 15 minutos via cron
# */15 * * * * /usr/local/bin/monitor-vps.sh
LOGWATCH Reporte diario automático del sistema
# Instalar logwatch
apt install logwatch

# Ver reporte del día en la terminal
logwatch --output stdout --range today --detail high

# Enviar reporte por email
logwatch --mailto tu@email.com --range yesterday --detail med

# Configurar envío diario automático
# /etc/logwatch/conf/logwatch.conf
MailTo = tu@email.com
Range  = yesterday
Detail = Med
Output = mail

# Logwatch ya configura su propio cron en /etc/cron.daily/
ls /etc/cron.daily/logwatch

Logwatch resume la actividad de SSH, sudo, Nginx, cron, paquetes instalados y más en un email diario — sin tener que revisar cada log manualmente.