Cómo programar tareas en Linux con cron y systemd
Para que un comando corra solo a una hora fija, abrí el crontab con crontab -e y agregá una línea con cinco campos de tiempo (minuto, hora, día del mes, mes y día de la semana) y el comando con su ruta completa: 30 3 * * * /usr/local/bin/respaldo.sh corre todos los días a las 3:30. Mandá la salida a un log para enterarte de los errores y escribí cada % como \%. En el hosting se hace igual desde la sección de tareas cron de DirectAdmin. Para correr algo cada vez que arranca el servidor, usá una unidad de systemd.
Cómo se lee una línea de cron
Cada línea del crontab es una tarea: cinco campos de tiempo separados por espacios y, después, el comando. La tarea corre cada vez que el reloj del servidor coincide con los cinco campos.
- Minuto: de 0 a 59.
- Hora: de 0 a 23.
- Día del mes: de 1 a 31.
- Mes: de 1 a 12.
- Día de la semana: de 0 a 7. El 0 y el 7 son domingo, y el 1, lunes.
- En cualquier campo,
*quiere decir todos los valores, la coma arma una lista (1,15), el guion un rango (1-5) y la barra un intervalo:*/10en los minutos es cada 10 minutos. - Si completás el día del mes y el día de la semana a la vez, alcanza con que se cumpla uno de los dos:
0 3 1 * 1corre el día 1 de cada mes y, además, todos los lunes.
Horarios de ejemplo
| Expresión | Cuándo corre |
|---|---|
*/5 * * * * | Cada 5 minutos. |
0 * * * * | Cada hora, en punto. |
30 3 * * * | Todos los días a las 3:30. |
0 9 * * 1-5 | Los días hábiles a las 9:00, de lunes a viernes. Los feriados no los distingue. |
0 4 * * 0 | Los domingos a las 4:00. |
0 3 1 * * | Una vez por mes, el día 1 a las 3:00. |
Las horas son las del reloj del servidor, en su zona horaria.
Crear la tarea con crontab -e
Cada usuario tiene su propio crontab. crontab -e abre el tuyo en un editor: guardás, cerrás y la tarea queda activa, sin reiniciar nada. Este ejemplo, en el crontab de root, tiene dos tareas:
MAILTO=juan@tudominio.com.ar
# Cada 5 minutos. Lo que imprima llega por correo a MAILTO
*/5 * * * * /usr/local/bin/revisar-sitio.sh
# Todos los días a las 3:30, con la salida en un log por mes
30 3 * * * /usr/local/bin/respaldo.sh >> /var/log/respaldo-$(date +\%Y-\%m).log 2>&1- La primera vez, Debian y Ubuntu pueden preguntarte qué editor usar: nano es el más simple. En AlmaLinux se abre vi; para usar nano,
EDITOR=nano crontab -e(si no está,dnf install nano). crontab -lmuestra las tareas cargadas, y como root,crontab -u juan -eedita las de otro usuario.- Revisá la zona horaria con
timedatectl. Para usar la de Argentina,timedatectl set-timezone America/Argentina/Buenos_Aires, y después reiniciá cron para que la tome:systemctl restart cronen Debian y Ubuntu,systemctl restart cronden AlmaLinux. - Si el comando
crontabno existe, instalalo:apt install cronen Debian y Ubuntu, odnf install cronieysystemctl enable --now cronden AlmaLinux.
Por qué anda a mano y no en cron
Casi siempre es el entorno. Cron no lee tu .bashrc ni tu perfil: cada tarea arranca con lo mínimo.
- El PATH de cron es corto:
/usr/bin:/binen Debian y Ubuntu, y en AlmaLinux suma/usr/sbiny/sbin. En ninguno está/usr/local/bin. Escribí la ruta completa de cada comando (command -v phpte la dice) o poné al principio del crontab una línea con todas las carpetas:PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin. - Lo que imprime la tarea, errores incluidos, se manda por correo al dueño del crontab o a la dirección de
MAILTO. Para que ese correo salga, el servidor necesita un programa de envío, como Postfix. Si no lo tiene, la salida se descarta y los errores pasan sin que te enteres. - Por eso conviene mandar todo a un log:
>> /var/log/mi-tarea.log 2>&1.>>agrega al final sin borrar lo anterior y2>&1suma los errores. ConMAILTO=""apagás el correo. - Los comandos los ejecuta
/bin/sh, no bash, y en Debian y Ubuntu eso es dash, que no entiende algunas construcciones de bash. Si la línea se complica, pasala a un script que empiece con#!/bin/bash, o ponéSHELL=/bin/bashal principio del crontab.
Tareas cron en el hosting, desde DirectAdmin
En el hosting no tenés acceso de root, pero DirectAdmin tiene su sección de tareas cron (Cronjobs), dentro de Funciones avanzadas. El formulario pide los mismos cinco campos y el comando, y la tarea corre con tu usuario del hosting.
Valen las mismas reglas: rutas completas, \% en lugar de % y la salida a un archivo de tu cuenta. Por ejemplo, para correr un script PHP todos los días a las 4:
- Minuto
0, hora4y*en los otros tres campos. - Comando:
/usr/local/bin/php /home/juan/domains/tudominio.com.ar/public_html/tarea.php >> /home/juan/cron.log 2>&1. En DirectAdmin, PHP está en/usr/local/bin/php, fuera del PATH de cron.
Un script al arrancar el servidor, con systemd
Para correr algo cada vez que arranca el servidor, usá una unidad de systemd: ves si falló, lo que imprime queda en el registro del sistema y podés hacer que espere a que la red esté lista. Creá /etc/systemd/system/mi-tarea.service:
[Unit]
Description=Mi tarea al arrancar
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/mi-tarea.sh
[Install]
WantedBy=multi-user.target- El script tiene que empezar con
#!/bin/bashy tener permiso de ejecución:chmod +x /usr/local/bin/mi-tarea.sh. systemctl daemon-reloadhace que systemd lea la unidad nueva. Repetilo cada vez que la edites.systemctl enable --now mi-tarea.servicela activa para cada arranque y además la corre en ese momento. Si no querés que corra ahora, usá soloenable.systemctl status mi-tarea.servicemuestra cómo terminó, yjournalctl -u mi-tarea.service, todo lo que imprimió.- En AlmaLinux, si creaste el script en otra carpeta y lo moviste con
mv, corrérestorecon -v /usr/local/bin/mi-tarea.sh. Si conserva la etiqueta de SELinux de la carpeta de origen, systemd no lo puede ejecutar. - Si en vez de un script que termina es un programa que queda corriendo, sacá
Type=oneshoty agregáRestart=on-failureen[Service]: systemd lo vuelve a levantar si se cae. ConUser=juancorre con ese usuario y no como root.
Timers de systemd, la alternativa a cron
Con systemd también se programan tareas por horario, con dos ventajas sobre cron: lo que imprime la tarea queda en el registro sin configurar nada y, con Persistent=true, si el servidor estaba apagado a la hora prevista, la tarea corre apenas arranca. Un timer activa la unidad .service de su mismo nombre. Para un respaldo diario a las 3:30, creá /etc/systemd/system/respaldo.timer:
[Unit]
Description=Respaldo diario
[Timer]
OnCalendar=*-*-* 03:30:00
Persistent=true
[Install]
WantedBy=timers.target- Al lado va
respaldo.service: igual a la unidad de arriba, con su propioExecStarty sin la sección[Install]. El que se habilita es el timer, no el servicio. - Activalo con
systemctl daemon-reloadysystemctl enable --now respaldo.timer. systemctl list-timersmuestra cuándo corre la próxima vez, ysystemd-analyze calendar "*-*-* 03:30:00"te deja probar una expresión antes de usarla.
Preguntas frecuentes
¿Cómo sé si la tarea corrió?
Cron anota cada ejecución en el registro del sistema: journalctl -t CRON en Debian y Ubuntu, journalctl -t CROND en AlmaLinux. Ahí ves que arrancó, no si terminó bien: para eso está el log al que mandaste la salida.
¿Sirve @reboot para correr algo al arrancar?
Para algo simple, sí: @reboot en lugar de los cinco campos corre el comando cuando arranca cron. Pero no espera a que la red esté lista y no tenés un systemctl status para ver cómo terminó. Para algo que importa, usá una unidad de systemd.
¿Cómo evito que una ejecución se pise con la anterior?
Si la tarea puede tardar más que el intervalo, corrila con flock: */5 * * * * /usr/bin/flock -n /tmp/revisar.lock /usr/local/bin/revisar-sitio.sh. Con -n, si la anterior sigue corriendo, la nueva no arranca. Con un timer de systemd no hace falta: no arranca una segunda copia mientras la primera sigue activa.
¿Dónde se guardan las tareas?
El crontab de cada usuario queda en /var/spool/cron/crontabs/ en Debian y Ubuntu, y en /var/spool/cron/ en AlmaLinux. No lo edites a mano: crontab -e revisa la sintaxis antes de guardar y te avisa si algo está mal.
Seguí leyendo
Cómo conectarte por SSH a tu servidor Linux desde Windows
Con la terminal que ya trae Windows 10 y 11, sin instalar nada: la primera conexión, las claves SSH, PuTTY como alternativa y qué hacer si no conecta.
Cómo crear un usuario administrador con sudo en Linux
Un usuario propio con sudo en Debian, Ubuntu y AlmaLinux, en vez de un segundo root: cómo crearlo, probarlo, cargarle tu clave SSH y limitar el acceso de root.
Cómo respaldar y restaurar tu hosting en DirectAdmin
Crear un respaldo desde el panel, elegir qué incluir, bajarlo, programarlo y restaurarlo. Y por qué una copia que queda en el mismo servidor no alcanza.