Los cron jobs son silenciosos por defecto. Se ejecutan en segundo plano, y cuando fallan — ya sea por un error de script, un timeout o una dependencia faltante — normalmente te enteras horas despues, cuando alguien nota que los datos no se procesaron o los backups no se ejecutaron.
La solucion es simple: recibir un mensaje en Slack en el momento en que un cron job termina con un error. Aqui te explico como hacerlo, desde un enfoque rapido con shell script hasta una configuracion mas limpia que funciona en todos tus jobs.
Opcion 1: Webhooks de Slack (La forma rapida)
Slack te permite crear una URL de Incoming Webhook para un canal. Vas a la configuracion de tu app de Slack, activas Incoming Webhooks, creas uno para el canal que quieras y obtienes una URL. Luego haces un POST:
#!/bin/bash SLACK_WEBHOOK="https://hooks.slack.com/services/T.../B.../..." # Run your job and capture the exit code python3 /home/deploy/scripts/process_orders.py EXIT_CODE=$? if [ $EXIT_CODE -ne 0 ]; then curl -s -X POST "$SLACK_WEBHOOK" \ -H "Content-Type: application/json" \ -d "{\"text\": \"Cron job failed (exit $EXIT_CODE): process_orders.py\"}" fi
Esto funciona. Pero en cuanto tengas mas de uno o dos jobs, te encontraras con los mismos problemas que vienen con cualquier configuracion directa de Slack Webhook:
- Una URL de webhook por canal. Si tienes cinco cron jobs publicando en diferentes canales, estas gestionando cinco secretos en cinco crontabs.
- La URL del webhook es el secreto. Esta hardcodeada o almacenada en un shell script en tu servidor. Si se filtra o se rota, actualizas cada script manualmente.
- Solo Slack. Si alguien de tu equipo prefiere Telegram, o quieres que el ingeniero de guardia reciba una notificacion en el telefono a las 3 AM, eso es una integracion separada.
- Sin historial. No hay registro de lo que se envio, cuando, o si alguien lo vio.
Para un solo script en un proyecto personal, los webhooks estan perfectamente bien. Para un servidor de produccion con multiples jobs, se convierte en un dolor de cabeza de mantenimiento.
Opcion 2: Una API de notificaciones (La forma limpia)
En lugar de llamar a Slack directamente, envias la alerta a una API de notificaciones que se encarga de la entrega. Con NotificationsBot, una sola llamada a la API puede llegar a Slack, Telegram, Discord o Email — quien sea que este suscrito a ese canal. Gestionas los suscriptores en un panel, no en tus scripts de cron.
curl -s -X POST https://api.notificationsbot.com/event \ -H "Authorization: Bearer $NOTIFICATIONSBOT_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "channel": "cron-alerts", "title": "Cron job failed", "message": "process_orders.py exited with code 1" }'
Una API key, un endpoint, todos tus jobs. Si quieres agregar un miembro del equipo a las alertas, lo agregas en el panel. No se requieren cambios en los scripts.
Con webhooks de Slack, tus scripts de cron estan acoplados a Slack. Con una API de notificaciones, tus scripts solo reportan lo que paso y el enrutamiento se maneja por separado. Puedes agregar nuevos destinatarios, cambiar de plataforma o dividir alertas en canales sin tocar un solo crontab.
Configurando alertas de Slack con NotificationsBot
Si aun no tienes una cuenta, la configuracion toma unos 5 minutos:
- Registrate en app.notificationsbot.com — plan gratuito, sin tarjeta de credito
- Crea un canal (por ejemplo,
cron-alerts) - Agrega un suscriptor y elige Slack como plataforma
- Vincula el suscriptor — conecta su cuenta de Slack a traves del flujo de onboarding
- Asigna el suscriptor al canal
- Crea una API key en Settings y guardala como variable de entorno en tu servidor
A partir de aqui, cualquier evento enviado a cron-alerts
llega a Slack. Puedes agregar mas suscriptores despues —
diferentes personas, diferentes plataformas — sin cambiar tus
scripts.
Un wrapper de shell reutilizable
El patron mas limpio es una pequena funcion wrapper que importas en cada script de cron. Ejecuta el job y dispara una alerta solo cuando falla, incluyendo el codigo de salida y cualquier output.
#!/bin/bash # /usr/local/bin/notify.sh notify_on_failure() { local job_name="$1" shift local output output=$("$@" 2>&1) local exit_code=$? if [ $exit_code -ne 0 ]; then local msg="Exit code: $exit_code" if [ -n "$output" ]; then msg="$msg\n\n$output" fi curl -s -X POST https://api.notificationsbot.com/event \ -H "Authorization: Bearer $NOTIFICATIONSBOT_API_KEY" \ -H "Content-Type: application/json" \ -d "{ \"channel\": \"cron-alerts\", \"title\": \"Cron failed: $job_name\", \"message\": \"$msg\" }" fi return $exit_code }
Luego tu crontab queda limpio y consistente:
NOTIFICATIONSBOT_API_KEY=your_api_key_here # Every night at 2 AM — fails silently without the wrapper 0 2 * * * source /usr/local/bin/notify.sh && notify_on_failure "nightly-backup" /home/deploy/scripts/backup.sh # Every 15 minutes */15 * * * * source /usr/local/bin/notify.sh && notify_on_failure "order-sync" python3 /home/deploy/scripts/sync_orders.py # Every hour 0 * * * * source /usr/local/bin/notify.sh && notify_on_failure "report-generator" node /home/deploy/scripts/generate_reports.js
Cron jobs en Python
Si tu cron job es un script de Python, puedes agregar notificaciones de fallo directamente en el manejador de excepciones:
import os import sys import requests import traceback API_KEY = os.environ["NOTIFICATIONSBOT_API_KEY"] def alert_failure(job: str, error: str): requests.post( "https://api.notificationsbot.com/event", headers={"Authorization": f"Bearer {API_KEY}"}, json={ "channel": "cron-alerts", "title": f"Cron failed: {job}", "message": error, }, timeout=5, ) if __name__ == "__main__": try: main() except Exception: alert_failure("process-orders", traceback.format_exc()) sys.exit(1)
Esto te da el traceback completo en el mensaje de Slack, para que sepas exactamente que fallo y donde — no solo que el job termino con codigo 1.
Cron jobs en Node.js
// run with: node sync_orders.js async function main() { // your cron job logic here } async function alertFailure(job, error) { await fetch("https://api.notificationsbot.com/event", { method: "POST", headers: { "Authorization": `Bearer ${process.env.NOTIFICATIONSBOT_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ channel: "cron-alerts", title: `Cron failed: ${job}`, message: error.message || String(error), }), }); } main().catch(async (err) => { await alertFailure("sync-orders", err); process.exit(1); });
Slack Webhooks vs NotificationsBot
- Configuracion por job — Webhooks: una URL que gestionar por canal. NotificationsBot: una API key para todos los jobs
- Multi-plataforma — Webhooks: solo Slack. NotificationsBot: Slack + Telegram + Discord + Email
- Gestion de destinatarios — Webhooks: quien sea que este en el canal. NotificationsBot: gestiona suscriptores desde un panel
- Detalles de fallos — Ambos soportan mensajes personalizados; NotificationsBot almacena un historial de eventos buscable
- Rotacion de secretos — Webhooks: actualizar cada script en el servidor. NotificationsBot: rotar la API key una vez en settings
- Agregar un nuevo destinatario — Webhooks: agregarlo al canal de Slack. NotificationsBot: agregar un suscriptor en el panel, sin cambios en scripts
Solo alerta en caso de fallo, no en cada ejecucion. Un cron job que se ejecuta 96 veces al dia y siempre tiene exito no deberia generar 96 mensajes en Slack. La funcion wrapper de arriba ya maneja esto — se mantiene en silencio cuando todo va bien y alerta solo cuando algo sale mal.
Bonus: Escalamiento de guardia
Una de las configuraciones mas utiles para produccion es que los fallos de cron notifiquen tanto a un canal de Slack (para todo el equipo) como a un suscriptor de Telegram (para el telefono del ingeniero de guardia). El equipo ve la alerta en Slack durante horas de trabajo, y la persona de guardia recibe un ping personal en Telegram a las 2 AM cuando el backup nocturno falla.
Con NotificationsBot, esto es solo agregar dos suscriptores al
mismo canal cron-alerts — uno de Slack, uno de
Telegram. Los scripts de cron no cambian en absoluto.
Nunca mas te pierdas un cron job fallido
Configura una cuenta gratuita, agrega un suscriptor de Slack y conecta tu primera alerta de cron job en menos de 10 minutos.
Comenzar gratis