Blog · 12 de octubre de 2026

El cron que dejó de correr

El respaldo de anoche, el corte de caja, los recordatorios a tus clientes. Un cron que no corre no truena: simplemente no pasa nada, y nadie lo nota hasta que hace falta lo que debió hacer. Aquí, cómo saber si corrió, las causas más comunes y cómo enterarte el mismo día.

1. ¿Corrió? Dónde revisarlo

En un servidor con Linux

En Vercel

En GitHub Actions

2. Las causas más comunes

Lo que pasaQué suele serCómo se arregla
A mano funciona, en cron noCron corre con un entorno mínimo: un PATH corto, sin las variables de tu .env y desde otro directorio.Rutas absolutas (/usr/bin/node), cd al proyecto en la misma línea y tus variables cargadas de forma explícita.
Corre, pero a otra horaEl servidor está en UTC. 0 2 * * * corre a las 8 de la noche en la Ciudad de México. GitHub Actions también usa UTC.Convierte la hora, o fija la zona (en GitHub Actions, la clave timezone).
La línea se corta a la mitadEn el crontab, % significa salto de línea: date +%F no llega completo.Escríbelo como \%, o pasa el comando a un script.
Dejó de correr después de un despliegue o un reinicioEl crontab vivía en el servidor viejo, el servicio de cron no arrancó, o tu contenedor no tiene cron.Que el crontab viva en tu repositorio y se instale al desplegar, o usa el programador de tu plataforma.
Corre, pero falla en silencioLa salida se va al correo local del servidor, que nadie lee, o a ningún lado.Manda la salida a un archivo: >> /var/log/corte.log 2>&1.
A veces corre dos veces a la vezTarda más que su intervalo y la siguiente corrida empieza antes de que acabe la anterior.flock -n para que no se encimen.
En Vercel, a cualquier minuto o una sola vezEn el plan Hobby, los cron corren una vez al día y en cualquier minuto de su hora. Una expresión más frecuente falla al desplegar.Pro, si necesitas el minuto exacto o más de una vez al día.
En GitHub Actions, tarde o nuncaCon mucha carga, schedule se retrasa y puede saltarse corridas. Solo corre en la rama principal, y en repositorios públicos se desactiva tras 60 días sin actividad.No lo uses para lo que no puede fallar, o vigílalo desde afuera.

3. Hazlo visible

Una línea de crontab que se defiende sola: entra al proyecto, no se encima con la corrida anterior y guarda lo que pasó.

# cada 15 minutos, en el directorio del proyecto, sin encimarse, con su log
*/15 * * * * cd /srv/tienda && /usr/bin/flock -n /tmp/conciliar.lock /usr/bin/node scripts/conciliar.js >> /var/log/conciliar.log 2>&1

Y que el script diga cuándo empezó, cuándo terminó y cuánto tardó, y salga con código distinto de cero si falló. Con eso, cuando algo pase, sabrás qué fue.

4. Alguien tiene que esperarlo desde afuera

Todo lo anterior sirve cuando el cron corre. Pero si no corre, no escribe nada: no hay log, no hay error, no hay nada que revisar. Un cron no puede avisar que no corrió.

La única forma de enterarte es que algo de afuera espere su señal y, si no llega a tiempo, avise. Es la idea del «latido»: el cron avisa «ya corrí», y otro sistema nota cuando ese aviso falta.

Si lo haces tú, el vigilante no puede vivir en el mismo servidor que el cron: si el servidor se cae, se caen los dos y nadie avisa.

5. Que te avise solo

Con Estiaje, conectas el SDK en tu script y no declaras nada más:

import { estiajeFromEnv } from '@estiaje/sdk';

const estiaje = estiajeFromEnv({ service: 'corte-de-caja' });
const corrida = new Date().toISOString().slice(0, 10);

estiaje.event('corte.empezo', { corrida });
try {
  await hacerCorte();
  estiaje.outcome('corte.termino', { corrida });
} catch (err) {
  estiaje.outcome('corte.fallo', { corrida, motivo: err.message });
  process.exitCode = 1;
}
await estiaje.flush();   // un script termina enseguida: espera el envío

Y en el panel, la expectativa: si a la hora de corte.empezo no llega corte.termino ni corte.fallo, te avisa. Un fallo que tu código detectó también se cuenta, aparte.

¿Python, PHP, Ruby o Go? En docs está la receta de cada uno, con cómo esperar el envío antes de salir.

Prueba 14 días de Pro, sin tarjeta Al terminar, sigues en Gratis con 3 procesos vigilados.

Preguntas frecuentes

¿Por qué mi cron funciona a mano pero no desde el crontab?

Porque cron corre con un entorno mínimo: un PATH corto, sin las variables de tu sesión ni de tu .env, y desde otro directorio. Usa rutas absolutas, haz cd al proyecto en la misma línea y carga tus variables de forma explícita.

¿Qué zona horaria usa cron?

La del servidor, que casi siempre está en UTC: 0 2 * * * corre a las 8 de la noche en la Ciudad de México. GitHub Actions también usa UTC, salvo que pongas la clave timezone.

¿Cómo veo si mi cron corrió en Linux?

En Debian y Ubuntu, con grep CRON /var/log/syslog o journalctl -u cron. Ahí ves si cron lanzó el comando, pero no si terminó bien: para eso hay que mandar su salida a un archivo de log.

¿Por qué no corre mi cron de Vercel?

Los cron de Vercel solo corren en el despliegue de producción. En el plan Hobby solo pueden correr una vez al día y en cualquier minuto de su hora: uno a la 1:00 corre entre la 1:00 y la 1:59.

Fuentes: la documentación de Vercel Cron Jobs (vercel.com/docs/cron-jobs) y de GitHub Actions (docs.github.com, el evento schedule), revisadas el 12 de octubre de 2026.

Sigue leyendo