Cheat Sheet de Crontab: 50+ expresiones cron, sintaxis y guía de planificadores modernos
Una expresión cron son cinco campos (minuto, hora, día del mes, mes, día de la semana) seguidos de un comando. Esa gramática mueve la planificación en Unix desde 1979 y hoy también mueve los CronJobs de Kubernetes, GitHub Actions, AWS EventBridge y los disparadores cron de Vercel. Se aprende una vez y se reutiliza en cualquier parte.
Esta página está pensada para quienes necesitan una expresión ahora mismo: una tarea de Linux, un CronJob de Kubernetes, un disparador de GitHub Actions, o averiguar por qué un job de cinco minutos solo se dispara cada hora. Salta a la Tabla de Referencia Rápida para copiar expresiones, a Sintaxis al Detalle para las reglas de cada campo, o abre el Generador Crontab — una alternativa privacy-first a crontab guru que corre en tu navegador — para validarlas en vivo.
Tabla de referencia rápida de expresiones cron
Treinta expresiones que cubren ~90% de las necesidades reales de programación. Cada una es cron POSIX de cinco campos válido: pégalas en crontab -e, en un schedule: de Kubernetes o en un cron: de GitHub Actions.
| Programación | Expresión cron | En palabras |
|---|---|---|
| Cada minuto | * * * * * | cada minuto, todo el día, todos los días |
| Cada 5 minutos | */5 * * * * | minuto 0, 5, 10, …, 55 |
| Cada 15 minutos | */15 * * * * | minuto 0, 15, 30, 45 |
| Cada 30 minutos | */30 * * * * | minuto 0 y 30 |
| Cada hora | 0 * * * * | en punto de cada hora |
| Cada 2 horas | 0 */2 * * * | hora 0, 2, 4, …, 22 |
| Cada 6 horas | 0 */6 * * * | hora 0, 6, 12, 18 |
| Dos veces al día (9 AM + 9 PM) | 0 9,21 * * * | minuto 0 de las horas 9 y 21 |
| Cada día laborable a las 9 AM | 0 9 * * 1-5 | lun-vie 09:00 |
| Cada fin de semana a las 9 AM | 0 9 * * 0,6 | sáb y dom 09:00 |
| Diario a medianoche | 0 0 * * * | todos los días 00:00 |
| Diario a las 2:30 AM | 30 2 * * * | ventana de batch con poco tráfico |
| Cada lunes a las 9 AM | 0 9 * * 1 | lunes 09:00 |
| Cada viernes a las 5 PM | 0 17 * * 5 | viernes 17:00 |
| Cada domingo a medianoche | 0 0 * * 0 | equivalente a @weekly |
| Día 1 del mes a medianoche | 0 0 1 * * | día 1 a las 00:00 — equivalente a @monthly |
| Día 15 de cada mes al mediodía | 0 12 15 * * | ventana de mitad de mes para nómina |
| Comprobación del último día (wrapper) | 0 0 28-31 * * + script | requiere una comprobación de fecha |
| Trimestral (1° de ene/abr/jul/oct) | 0 0 1 JAN,APR,JUL,OCT * | primer día de cada trimestre |
| Anual (1 de enero) | 0 0 1 1 * o @yearly | medianoche de año nuevo |
| Cada 5 min, días laborables 9-5 | */5 9-17 * * 1-5 | sondeo en horario laboral |
| Cada 30 min en fines de semana | */30 * * * 0,6 | monitoreo sáb/dom |
| Dos veces por hora, 15 y 45 | 15,45 * * * * | desfase respecto a la avalancha del :00 |
| Primer lunes (wrapper) | 0 9 1-7 * 1 + chequeo AND | hace falta wrapper (ver abajo) |
| Macros | @hourly @daily @weekly @monthly @yearly | no estándar pero ampliamente soportadas |
| Solo al reiniciar | @reboot | no estándar, solo vixie cron |
Pega cualquiera en el Generador Crontab para previsualizar las próximas cinco ejecuciones antes de desplegar.
Sintaxis de cron al detalle: los 5 campos
Una expresión cron son cinco campos separados por espacios más un comando. Cada campo controla una porción de la programación. Es la misma sintaxis en todos los planificadores que aparecen en esta guía.
┌──────────── minuto (0 - 59)
│ ┌────────── hora (0 - 23)
│ │ ┌──────── día del mes (1 - 31)
│ │ │ ┌────── mes (1 - 12 o JAN-DEC)
│ │ │ │ ┌──── día de semana (0 - 6 o SUN-SAT; 0 y 7 significan domingo)
│ │ │ │ │
* * * * * comando-a-ejecutar
Regla mnemotécnica: “Mi Hermano Diego Madruga Siempre” — Minuto, Hora, Día del mes, Mes, Semana (día de). De izquierda a derecha, de la unidad más pequeña a la más grande.
Valores permitidos campo por campo
| Campo | Rango | Alias | Notas |
|---|---|---|---|
| Minuto | 0-59 | ninguno | 0 significa “en punto” |
| Hora | 0-23 | ninguno | reloj de 24 horas; 0 es medianoche, 12 es mediodía |
| Día del mes | 1-31 | ninguno | los días inválidos para un mes simplemente nunca se disparan (31 de febrero) |
| Mes | 1-12 | JAN, FEB, MAR, …, DEC | no distingue mayúsculas y minúsculas |
| Día de la semana | 0-7 | SUN, MON, TUE, …, SAT | tanto 0 como 7 significan domingo |
Operadores al detalle
Cinco operadores cubren cualquier expresión cron estándar:
| Operador | Significado | Ejemplo | Se expande a |
|---|---|---|---|
* | cualquier valor | * * * * * | cada minuto |
, | lista | 0 9,12,17 * * * | 09:00, 12:00, 17:00 |
- | rango inclusivo | 0 9-17 * * * | cada hora de 09:00 a 17:00 |
/ | paso | */15 * * * * | minuto 0, 15, 30, 45 |
| mixto | combinado | 0 9-12,14-17 * * * | mañana + tarde, sin la hora del almuerzo |
El operador de paso merece atención. */N se ancla al valor más bajo del campo, no al instante actual. */15 significa “minuto 0, 15, 30, 45 de cada hora”, no “cada 15 minutos desde ahora”. Si guardas a las 12:03, la próxima ejecución es a las 12:15. Con una base que no sea comodín, 5/15 se lee “empieza en 5, luego cada 15”: minuto 5, 20, 35, 50.
Meses y días de la semana con nombre
Escribe meses y días de la semana como nombres, sin distinguir mayúsculas:
0 0 1 JAN,APR,JUL,OCT * # primer día de cada trimestre
0 9 * * MON-FRI # laborables a las 9 AM
0 17 * * FRI # viernes a las 5 PM
Los nombres se leen mejor en revisiones de código; las formas numéricas son ligeramente más portables. Elige un estilo por proyecto.
Macros no estándar: @reboot, @daily y compañía
La mayoría de las implementaciones de cron aceptan seis macros de atajo:
| Macro | Se expande a | Significado |
|---|---|---|
@yearly / @annually | 0 0 1 1 * | una vez al año, 1 de enero a medianoche |
@monthly | 0 0 1 * * | día 1 de cada mes a medianoche |
@weekly | 0 0 * * 0 | cada domingo a medianoche |
@daily / @midnight | 0 0 * * * | cada día a medianoche |
@hourly | 0 * * * * | en punto de cada hora |
@reboot | (especial) | una sola vez al arrancar el daemon de cron |
Estas macros no son estándar: vixie cron y cronie las soportan, pero los CronJob de Kubernetes, GitHub Actions y AWS EventBridge no. Para expresiones portables, escribe la forma de cinco campos. @reboot rara vez funciona en contenedores donde el daemon de cron puede no ser el proceso init.
50+ expresiones cron listas para copiar (agrupadas por caso de uso)
La Tabla de Referencia Rápida cubre los casos comunes. Esta sección añade seis grupos con ejemplos más densos.
Cada N minutos
* * * * * # cada minuto
*/2 * * * * # cada 2 minutos
*/5 * * * * # cada 5 minutos — el caso clásico de "cada 5 minutos"
*/10 * * * * # cada 10 minutos
*/15 * * * * # cada 15 minutos
*/30 * * * * # cada 30 minutos
0,30 * * * * # minutos 0 y 30 explícitos (igual que */30)
*/45 * * * * # OJO: solo se dispara en 0 y 45, luego se reinicia
*/45 es una trampa habitual: el minuto va de 0 a 59, así que cae en 0 y 45 y luego salta al inicio de la siguiente hora. Para una verdadera cadencia de 45 minutos necesitas un worker externo.
Variantes por hora
0 * * * * # cada hora en el :00
30 * * * * # cada hora en el :30
0 */2 * * * # cada 2 horas, hora par
0 */6 * * * # cada 6 horas
0 */12 * * * # dos veces al día, 00:00 y 12:00
15 */2 * * * # cada 2 horas, desfase de 15 min (evita el pico del :00)
Diarios a horas específicas
0 0 * * * # medianoche (= @daily / @midnight)
30 2 * * * # 02:30 — ventana de batch con poco tráfico
0 9 * * * # 09:00
45 23 * * * # 23:45 — cierres de fin de día
0 9,12,17 * * * # tres veces al día
0 9-17 * * * # cada hora de 09:00 a 17:00
Programaciones semanales
0 9 * * 1-5 # laborables a las 9 AM
0 9 * * 0,6 # fines de semana a las 9 AM
0 18 * * 5 # viernes a las 6 PM
0 0 * * 0 # domingo a medianoche (= @weekly)
0 9 * * MON,WED,FRI # lun/mié/vie a las 9 AM
*/30 9-17 * * 1-5 # cada 30 min, horario laboral, días laborables
Mensuales y trimestrales
0 0 1 * * # día 1 del mes a medianoche (= @monthly)
0 0 15 * * # día 15 — ventana de nómina
0 0 1,15 * * # día 1 y 15 — quincenal
0 0 1 */3 * # trimestral: primero de ene, abr, jul, oct
0 0 1 JAN,APR,JUL,OCT * # lo mismo, con meses nombrados
0 0 28-31 * * # los últimos días — combina con un wrapper que valide la fecha
El último día del mes no tiene expresión nativa en POSIX. Ejecuta un wrapper que compruebe date -d tomorrow +%d = 01, o usa un planificador con soporte nativo (Quartz tiene L; Kubernetes no).
Anuales y atajos con macros
0 0 1 1 * # 1 de enero a medianoche (= @yearly / @annually)
0 0 25 12 * # Navidad a medianoche
@yearly # = 0 0 1 1 *
@monthly # = 0 0 1 * *
@weekly # = 0 0 * * 0
@daily # = 0 0 * * *
@hourly # = 0 * * * *
@reboot # especial: una vez al iniciar el daemon (solo vixie cron)
Pega cualquiera de estas expresiones en el Generador Crontab para previsualizar las próximas cinco ejecuciones antes de desplegar.
Cron vs timers de systemd vs planificadores en la nube: matriz de decisión
Cron es la opción por defecto, no siempre la mejor. Comparativa de los siete planificadores más comunes, útil para decidir entre cron y systemd timer, Kubernetes CronJob frente a cron job de Vercel, o para migrar de crontab a una nube gestionada.
| Característica | vixie cron | timer de systemd | K8s CronJob | GHA schedule | AWS EventBridge | Vercel Cron | Cloudflare Workers |
|---|---|---|---|---|---|---|---|
| Sintaxis de campos | POSIX 5 campos | spec OnCalendar | POSIX 5 campos + timeZone | POSIX 5 campos | Quartz 6 campos con ? | POSIX 5 campos | POSIX 5 campos |
| Intervalo mínimo | 1 minuto | 1 segundo | 1 minuto | best-effort, ≥15 min recomendado | 1 minuto | 1 minuto (plan Pro) | 1 minuto |
| Zona horaria explícita | CRON_TZ= | Persistent=true | spec.timeZone (1.27+) | solo UTC | ScheduleExpressionTimezone | solo UTC | solo UTC |
| Recuperación de ejecuciones perdidas | no (usa anacron) | sí (Persistent=true) | sí (startingDeadlineSeconds) | no | sí | no | no |
| Reintentos / backoff | no | parcial | sí (backoffLimit) | reintento al fallar | sí | no | sí |
| Control de concurrencia | no (usa flock) | parcial | sí (concurrencyPolicy) | no | no | no | no |
Soporte de @reboot | sí | sí (vía OnBootSec=) | no | no | no | no | no |
Timers de systemd: cuándo preferirlos sobre cron
En Linux basado en systemd, los timers son una alternativa seria: sintaxis de calendario legible, integración con el journal y recuperación de ejecuciones perdidas. Un timer y su servicio correspondiente:
# daily-report.timer
[Unit]
Description=Run daily report at 9 AM
[Timer]
OnCalendar=*-*-* 09:00:00
Persistent=true
Unit=daily-report.service
[Install]
WantedBy=timers.target
# daily-report.service
[Unit]
Description=Daily report job
[Service]
Type=oneshot
ExecStart=/usr/local/bin/daily-report.sh
User=reporter
Actívalo con systemctl enable --now daily-report.timer. La pieza diferenciadora es Persistent=true: si la máquina estaba apagada a las 9 AM, el timer se dispara en cuanto arranca; vixie cron no tiene equivalente sin anacron. Para reforzar la seguridad del servicio, mira nuestras mejores prácticas de seguridad.
Kubernetes CronJob
Kubernetes envuelve la programación POSIX con primitivas para concurrencia, historial y zona horaria explícita:
apiVersion: batch/v1
kind: CronJob
metadata:
name: nightly-report
spec:
schedule: "0 2 * * *"
timeZone: "America/New_York" # Kubernetes 1.27+
concurrencyPolicy: Forbid # nunca correr dos a la vez
startingDeadlineSeconds: 300 # saltar si se retrasa más de 5 min
jobTemplate:
spec:
backoffLimit: 2
template:
spec:
restartPolicy: OnFailure
containers:
- name: reporter
image: reporter:1.4.0
command: ["/usr/local/bin/report.sh"]
concurrencyPolicy: Forbid es tu equivalente a flock. Sin él, un job de larga duración se apila sobre su sucesor. Mira la sección de referencia de campos para todas las perillas.
Particularidades de GitHub Actions schedule
GitHub Actions acepta cron POSIX estándar de cinco campos:
on:
schedule:
- cron: '0 9 * * 1-5' # laborables a las 9 AM UTC
Best-effort: bajo alta carga en los runners de GitHub, los jobs pueden dispararse minutos tarde o saltarse por completo. Evita intervalos menores a quince minutos. No hay ajuste de zona horaria: siempre UTC.
AWS EventBridge: cron estilo Quartz de seis campos
AWS EventBridge usa un cron al estilo Quartz con seis campos y un ? obligatorio en uno de los dos campos de día:
cron(0 9 * * ? *)
Orden de los campos: Minutos Horas Día-del-mes Mes Día-de-la-semana Año. Uno de los dos campos de día debe ser ? cuando el otro está restringido (es la forma de Quartz de resolver la ambigüedad OR de POSIX). Una copia directa desde un crontab de Linux no pasa la validación.
Vercel Cron, Cloudflare Workers, Render Cron Jobs
Las plataformas serverless más nuevas se estandarizan en POSIX de cinco campos. Un cron job de Vercel vive en vercel.json como { "crons": [{ "path": "/api/cron/nightly", "schedule": "0 2 * * *" }] }. Los Cron Triggers de Cloudflare Workers usan wrangler.toml:
[triggers]
crons = ["*/15 * * * *", "0 9 * * 1-5"]
Render usa render.yaml. Las tres corren en UTC sin override de zona horaria por programación, así que conviene diseñar en UTC desde el inicio.
7 trampas al depurar cron (y cómo detectarlas)
La mayoría de los reportes de “mi cron job no corre” tienen una de siete causas raíz. Revisa esta lista antes de culpar al planificador.
Trampa 1: el PATH es mínimo
Cron arranca los jobs con un $PATH mínimo, típicamente /usr/bin:/bin. Tu shell interactiva tiene /usr/local/bin, ~/.cargo/bin y una docena de entradas de .bashrc. Ninguna existe dentro de cron. Es la causa más frecuente al depurar el entorno PATH de cron.
Síntoma: node: command not found. Solución: define PATH al inicio del crontab, o usa rutas absolutas.
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin
*/15 * * * * /usr/local/bin/poll-api.sh
0 9 * * * /home/deploy/.cargo/bin/my-rust-cli
Trampa 2: stdout y stderr se pierden en silencio
Por defecto, la salida de cron va a un buzón de correo que nadie lee. El job falla en silencio. Redirige ambos flujos:
*/15 * * * * /usr/local/bin/job.sh >> /var/log/job.log 2>&1
Para salida JSON, encadena con jq; para extraer líneas de log, mira nuestro cheat sheet de regex. Para timers de systemd, journalctl -u tu-timer.service captura la salida.
Trampa 3: desfase de zona horaria entre dev y producción
Escribiste 0 9 * * * en tu laptop en Nueva York esperando que se dispare a las 9 AM hora del Este. El servidor corre en UTC. El cron se dispara a las 9 AM UTC: las 4 AM hora del Este, antes de que nadie lo note. Solución: pon los servidores en UTC y escribe las programaciones en UTC, o fija la zona horaria explícitamente.
CRON_TZ=America/New_York
0 9 * * * /usr/local/bin/morning-report.sh
CRON_TZ funciona en vixie cron 3.0+; Kubernetes 1.27+ tiene spec.timeZone; AWS EventBridge tiene ScheduleExpressionTimezone; GitHub Actions siempre es UTC. Para UTC, horario de verano y matemáticas con epoch, mira nuestra guía del timestamp Unix.
Trampa 4: % sin escapar en los comandos
Cron interpreta los % sin escapar como saltos de línea: el resto de la línea se alimenta al comando como stdin. Por eso date +"%Y-%m-%d" se rompe. Escapa cada % como \%, o mueve la lógica a un script:
0 0 * * * echo "Run at $(date +"\%Y-\%m-\%d")" >> /tmp/log
Trampa 5: ejecuciones solapadas
Un job */5 * * * * que de vez en cuando tarda siete minutos arrancará la siguiente instancia antes de que termine la anterior. Dos copias pelean por la misma fila, el mismo archivo de lock y la misma cuota de API. Serialízalo con flock:
*/5 * * * * flock -n /tmp/job.lock /usr/local/bin/job.sh
-n sale inmediatamente si el lock está tomado. Para Kubernetes, define concurrencyPolicy: Forbid. Los permisos del archivo de lock importan: mira las mejores prácticas de seguridad.
Trampa 6: @reboot en contenedores
@reboot corre una vez cuando arranca el daemon de cron. En una VM eso coincide con el boot. En un contenedor el daemon de cron normalmente no es PID 1 y puede no estar corriendo siquiera. No uses @reboot en contenedores: pon la lógica de “ejecutar una vez al arrancar” en tu entrypoint o en un init container.
Trampa 7: la semántica OR de día del mes / día de la semana en POSIX
La trampa de cron más cara. Regla POSIX: cuando tanto día del mes como día de la semana están restringidos (ninguno es *), la programación se dispara cuando cualquiera de los dos coincide.
0 0 1 * 5 parece “medianoche del día 1, solo los viernes”, pero se dispara el día 1 Y todos los viernes: entre seis y diez disparos extra al mes.
# MAL: parece "día 1 del mes, solo si es viernes"
0 0 1 * 5
# BIEN: elige una sola restricción
0 0 1 * * # cada día 1 del mes
0 0 * * 5 # cada viernes
# La semántica AND requiere un wrapper
0 0 1-7 * 5 [ "$(date +\%u)" = "5" ] && /script # solo el primer viernes
Pega las expresiones sospechosas en el Generador Crontab; la previsualización de la próxima ejecución hace visible la trampa OR.
Planificadores modernos: cuándo NO usar cron
Cron es adecuado para “ejecuta este comando aproximadamente a esta hora, con una cadencia fija”. No es adecuado para varios problemas vecinos:
- Flujos de trabajo con dependencias (correr A, luego B si A tuvo éxito) → Airflow, Prefect, Dagster.
- Reintentos, backoff exponencial, colas de mensajes muertos → Temporal, AWS Step Functions, Sidekiq.
- Intervalos menores a un minuto → un worker de larga duración que duerme entre iteraciones.
- Precisión al segundo → un daemon dedicado; los planificadores gestionados no garantizan tiempos exactos.
- Trabajo dirigido por eventos → webhooks, colas de mensajes, streams de change-data-capture.
Cron no desaparece: Airflow, Step Functions y Sidekiq aceptan expresiones cron como entrada de sus flujos de trabajo. La gramática de cinco campos se reutiliza.
Referencia de campos de Kubernetes CronJob
La matriz de decisión más arriba mostraba un CronJob mínimo. Esta tabla cubre todos los campos relevantes de la sintaxis de cronjob en Kubernetes:
| Campo | Predeterminado | Qué hace |
|---|---|---|
schedule | obligatorio | expresión cron POSIX de 5 campos |
timeZone | TZ del controlador | zona horaria explícita (1.27+); usa nombres IANA |
concurrencyPolicy | Allow | Forbid salta nuevas ejecuciones mientras la anterior siga activa; Replace la cancela |
startingDeadlineSeconds | sin límite | salta si el retraso supera este valor |
successfulJobsHistoryLimit | 3 | número de Jobs exitosos a conservar |
failedJobsHistoryLimit | 1 | número de Jobs fallidos a conservar |
suspend | false | pausa sin borrar |
backoffLimit | 6 | reintentos del Pod antes de marcar el Job como Failed |
activeDeadlineSeconds | sin definir | tope duro al tiempo de ejecución del Pod |
ttlSecondsAfterFinished | sin definir | auto-eliminación del Job tras estos segundos |
Dos errores comunes: olvidar timeZone hace que la programación siga la zona horaria del host del kube-controller-manager (impredecible en Kubernetes gestionado); en una programación de un minuto, el valor por defecto successfulJobsHistoryLimit: 3 acumula tres objetos Job por minuto a menos que definas ttlSecondsAfterFinished.
Equivalentes de cron entre plataformas
macOS launchd. Apple recomienda launchd sobre cron. Un job de launchd es un .plist en ~/Library/LaunchAgents/:
<plist version="1.0"><dict>
<key>Label</key><string>com.example.daily</string>
<key>ProgramArguments</key><array><string>/usr/local/bin/daily.sh</string></array>
<key>StartCalendarInterval</key>
<dict><key>Hour</key><integer>9</integer><key>Minute</key><integer>0</integer></dict>
</dict></plist>
Cárgalo con launchctl load ~/Library/LaunchAgents/com.example.daily.plist. A diferencia de cron, launchd recupera las ejecuciones perdidas tras sleep/wake.
Programador de Tareas de Windows usa schtasks:
schtasks /create /tn "DailyReport" /tr "C:\scripts\report.bat" /sc DAILY /st 09:00
schtasks /create /tn "EveryFifteen" /tr "C:\scripts\poll.bat" /sc MINUTE /mo 15
En WSL, el cron nativo de Linux funciona pero se detiene cuando termina la sesión: usa el Programador de Tareas para lanzar jobs WSL siempre activos.
Cron en contenedores Docker. La mayoría de las imágenes slim (alpine, debian-slim, distroless) no incluyen daemon de cron. Instala cronie o busybox-cron y córrelo como PID 1 con tini o s6-overlay, o, casi siempre preferible, usa un CronJob de Kubernetes.
Consejos y patrones avanzados
Último día del mes
Cron no tiene operador nativo de “último día”. Ejecuta cada día en la ventana 28-31 y comprueba si mañana es día 1:
0 23 28-31 * * [ "$(date -d tomorrow +\%d)" = "01" ] && /usr/local/bin/eom.sh
Enésimo día de la semana del mes
“Primer lunes” usa el mismo patrón de wrapper: restringe a los días 1-7 y luego comprueba el día de la semana:
0 9 1-7 * * [ "$(date +\%u)" = "1" ] && /usr/local/bin/first-monday.sh
Para “último viernes”, usa los días 25-31 más la comprobación del día de la semana.
Desfase aleatorio para repartir carga
Cuando muchas máquinas corren el mismo cron, 0 0 * * * produce una estampida a medianoche UTC. Reparte con un retraso aleatorio:
RANDOM_DELAY=10 # cronie / anacron, en minutos
0 0 * * * /usr/local/bin/job.sh
0 0 * * * sleep $((RANDOM \% 600)); /usr/local/bin/job.sh # portable
Monitoreo con heartbeat
Cron falla en silencio. El patrón de “interruptor del hombre muerto”: el job hace ping a un servicio de monitoreo tras cada ejecución exitosa; el servicio alerta cuando un ping esperado no llega. Healthchecks.io, Cronitor y Dead Man’s Snitch ofrecen planes gratuitos.
*/15 * * * * /usr/local/bin/job.sh && curl -fsS --retry 3 https://hc-ping.com/your-uuid
Para lógica de monitoreo que ramifica según códigos de respuesta (200 saludable, 429 rate-limited, 503 degradado), mira nuestro cheat sheet de códigos de estado HTTP.
Diseña jobs idempotentes
Cron no tiene reintentos ni recuperación de ejecuciones perdidas ni control de concurrencia. La forma más fiable de compensarlo es hacer que el propio job sea seguro de ejecutar varias veces. En lugar de “envía el reporte de hoy a las 9 AM”, diséñalo como “envía el reporte de hoy si todavía no se envió”; las ejecuciones perdidas, los duplicados y los reintentos manuales convergen al mismo estado.
FAQ
¿*/5 * * * * realmente significa cada 5 minutos?
Casi — */5 * * * * está anclado al minuto 0, no a “cada 5 minutos desde ahora”. Se dispara en el minuto 0, 5, 10, …, 55 de cada hora. El paso */N es relativo al valor más bajo del campo, no al instante actual. Si guardas a las 12:03, la próxima ejecución es a las 12:05, no a las 12:08.
¿Qué significa 0 0 * * * en cron?
0 0 * * * significa todos los días a medianoche (00:00) en la zona horaria local del servidor. Campos: minuto 0, hora 0, cualquier día del mes, cualquier mes, cualquier día de la semana. Equivale a las macros @daily o @midnight. Para fijar la zona horaria, añade CRON_TZ=America/New_York al inicio del crontab.
¿Cómo ejecuto un cron job cada 30 segundos?
No puedes con cron POSIX estándar: la granularidad mínima es un minuto. Tres soluciones: dos jobs escalonados con * * * * * y sleep 30 && en uno; un timer de systemd con OnCalendar=*:*:0/30; o un worker de larga duración que duerma entre iteraciones. Lo último suele ser lo correcto.
¿Qué zona horaria usa cron por defecto?
La zona horaria local del sistema del servidor (/etc/timezone o la variable de entorno TZ). Un cron a las 9 AM en un servidor UTC se dispara a las 4 AM en la costa Este de EE. UU. Solución: define CRON_TZ= al inicio del crontab, o pon los servidores en UTC y diseña las programaciones en UTC. GitHub Actions siempre es UTC; Kubernetes 1.27+ soporta spec.timeZone.
¿Por qué mi cron job no se ejecuta?
Si tu cron job no se ejecuta, verifica en este orden: ¿está corriendo el daemon de cron (systemctl status cron); está definido $PATH en el crontab; está capturándose stderr (>> log 2>&1); está cargado el crontab del usuario (crontab -l); se escapó el % en los comandos; es la zona horaria la que esperas? La mayoría de los reportes de “no corre” son el segundo o el tercer punto.
¿La sintaxis de Kubernetes CronJob es igual a la de Linux cron?
Sí en el campo de programación: ambos usan cron POSIX de cinco campos. Kubernetes añade spec.timeZone (1.27+), concurrencyPolicy para controlar solapamientos, startingDeadlineSeconds para recuperar ejecuciones perdidas, y suspend: true para pausar. Linux cron no tiene nada de esto: tendrás que recurrir a flock y anacron.
¿Cuál es la diferencia entre @reboot y @daily?
@daily es una macro para 0 0 * * *: cada día a medianoche, con una programación fija. @reboot se ejecuta una vez cuando arranca el daemon de cron, sin programación recurrente. @reboot está soportado por vixie cron y cronie, pero no por Kubernetes CronJob, GitHub Actions ni AWS EventBridge. En contenedores, @reboot rara vez se dispara.
¿Cuál es la diferencia entre cron y crontab?
cron es el demonio en segundo plano que ejecuta tareas programadas; crontab es el archivo que las lista (y el comando crontab para editarlo). El demonio lee el crontab de cada usuario en un ciclo y ejecuta los comandos cuyo momento de ejecución coincide con la expresión cron. En resumen, cron es el motor y crontab es la receta.