Skip to content

Instantly share code, notes, and snippets.

@razametal
Created October 13, 2025 17:21
Show Gist options
  • Select an option

  • Save razametal/139cfe7e59fe146fb201f7016e4189e6 to your computer and use it in GitHub Desktop.

Select an option

Save razametal/139cfe7e59fe146fb201f7016e4189e6 to your computer and use it in GitHub Desktop.
Monitor de OSCAM y PCSCD
cat <<'EOF' | sudo tee /usr/local/bin/oscam_pcscd_monitor.sh > /dev/null
#!/bin/bash
#
# Monitor de oscam y pcscd
# Reinicia pcscd y luego oscam si:
# - pcscd no está activo
# - oscam no está activo
# - oscam está activo pero su API no responde (health check)
# - el log de oscam muestra errores de lector en los últimos 30 s
#
# Autor: Guillermo Salas <[email protected]>
# Fecha: 2025-08-05
#
# --------------------------
# CONFIGURACIÓN
# --------------------------
OSC_LOG="/var/log/oscam/oscam.log"
ERR_PATTERNS=("Error getting card status" "Error Reader Exclusive" "Cannot open device:")
MAX_AGE_SEC=30
LOCKFILE="/run/oscam_pcscd_monitor.lock"
LOG="/var/log/oscam_pcscd_monitor.log"
# --------------------------
# FUNCIONES
# --------------------------
# Función para registrar eventos en el log
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG"
}
# Función Health check de la API de OSCam
check_oscam_api() {
log "Verificando la API de OSCam en http://localhost:8888/oscamapi.html"
# Usamos curl para obtener solo el código de estado, con un timeout de 10s.
# -o /dev/null descarta el contenido, -s es silencioso, -w "%{http_code}" imprime solo el código.
local http_status
http_status=$(curl --max-time 10 -o /dev/null -s -w "%{http_code}" http://localhost:8888/oscamapi.html)
if [ "$http_status" -eq 401 ]; then
log "API de OSCam responde correctamente (HTTP 401 Unauthorized)."
return 0 # Éxito
else
log "La API de OSCam no responde como se espera. Código de estado recibido: $http_status"
return 1 # Fallo
fi
}
# Función para reiniciar los servicios de forma controlada
restart_both() {
log "Se detectó un problema. Procediendo a reiniciar los servicios."
log "Reiniciando pcscd..."
systemctl restart pcscd
if systemctl is-active --quiet pcscd; then
log "pcscd reiniciado con éxito."
else
log "ERROR: Falló el reinicio de pcscd."
fi
# Pequeña pausa para asegurar que pcscd esté completamente listo antes de reiniciar oscam
sleep 5
log "Reiniciando oscam..."
systemctl restart oscam
if systemctl is-active --quiet oscam; then
log "oscam reiniciado con éxito."
else
log "ERROR: Falló el reinicio de oscam."
fi
}
# --------------------------
# BLOQUEO
# --------------------------
exec 200>"$LOCKFILE"
flock -n 200 || { log "Monitor ya en ejecución, saliendo."; exit 0; }
RESTART_NEEDED=false
# --------------------------
# 1. ¿pcscd está activo?
# --------------------------
if ! systemctl is-active --quiet pcscd; then
log "pcscd no está activo."
RESTART_NEEDED=true
fi
# --------------------------
# 2. ¿oscam está activo Y responde?
# --------------------------
if ! systemctl is-active --quiet oscam; then
log "oscam no está activo."
RESTART_NEEDED=true
else
# Si oscam está activo, verificamos su API
if ! check_oscam_api; then
log "El servicio oscam está 'activo' pero su API no responde. Se requiere reinicio."
RESTART_NEEDED=true
fi
fi
# --------------------------
# 3. ¿Hay errores recientes en el log?
# --------------------------
if [[ -f "$OSC_LOG" ]]; then
current_time=$(date +%s)
while IFS= read -r line; do
log_timestamp_str=$(echo "$line" | awk '{print $1" "$2}')
log_time=$(date -d "$log_timestamp_str" +%s 2>/dev/null)
if [[ -n "$log_time" && $((current_time - log_time)) -le $MAX_AGE_SEC ]]; then
for pattern in "${ERR_PATTERNS[@]}"; do
if echo "$line" | grep -qF "$pattern"; then
log "Detectado error reciente en oscam.log: '$pattern'"
RESTART_NEEDED=true
break 2
fi
done
fi
done < <(tail -n 1000 "$OSC_LOG")
else
log "Advertencia: no se encontró el log de oscam en $OSC_LOG"
fi
# --------------------------
# 4. Reiniciar si es necesario
# --------------------------
if $RESTART_NEEDED; then
restart_both
else
log "Estado de servicios OK. No se requiere acción."
fi
EOF
# Dar permisos de ejecución:
sudo chmod +x /usr/local/bin/oscam_pcscd_monitor.sh
# Crear servicio en systemd para monitoreo y ejecución cada 30 minutos
cat <<EOF > /etc/systemd/system/oscam_pcscd_monitor.service
[Unit]
Description=Monitor oscam y pcscd
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/oscam_pcscd_monitor.sh
EOF
cat <<EOF > /etc/systemd/system/oscam_pcscd_monitor.timer
[Unit]
Description=Ejecuta el monitor de oscam/pcscd cada 30 minutos
Requires=oscam_pcscd_monitor.service
[Timer]
OnBootSec=10m
OnUnitActiveSec=30m
AccuracySec=1s
[Install]
WantedBy=timers.target
EOF
# Activar e iniciar el servicio
systemctl daemon-reload
systemctl enable oscam_pcscd_monitor.timer
systemctl start oscam_pcscd_monitor.timer
# Configurar la rotación de logs:
cat <<EOF > /etc/logrotate.d/oscam_pcscd_monitor
/var/log/oscam_pcscd_monitor.log {
weekly
rotate 7
compress
delaycompress
missingok
notifempty
create 640 root adm
}
EOF
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment