DevTools

Cheatsheet Cron Jobs

Agendamento de tarefas em sistemas Unix/Linux

Voltar às linguagens
Cron Jobs
23 cards encontrados
Categorias:
Versões:

Sintaxe e Campos


5 cards
Estrutura base
# ┌──────── minuto (0-59)
# │ ┌────── hora (0-23)
# │ │ ┌──── dia do mês (1-31)
# │ │ │ ┌── mês (1-12)
# │ │ │ │ ┌─ dia da semana (0-7)
# │ │ │ │ │
# * * * * * comando-a-executar

# 0 e 7 = domingo

Cada * representa um campo temporal. Os 5 campos definem QUANDO executar. O restante é o comando. A ordem é fixa: minuto, hora, dia, mês, semana. 0 e 7 ambos significam domingo.

Campo dia da semana
# Dia da semana (0-7, 0 e 7 = domingo)
0 9 * * 1      # segunda às 09:00
0 9 * * 1-5    # seg a sex às 09:00
0 0 * * 0      # domingo à meia-noite
0 9 * * MON    # = 1 (nomes: SUN-SAT)
0 9 * * 6,0    # sábado e domingo

# NOTA: se dia-mês E dia-semana forem
# restritos, executa em QUALQUER um (OR)

O quinto campo é o dia da semana (0-7). Aceita nomes: SUN, MON, TUE... Se ambos dia-mês e dia-semana estiverem restritos (não *), o cron executa quando QUALQUER corresponder (lógica OR, não AND).

Campo minuto
# Minuto (0-59)
0 * * * *    # no início de cada hora
30 * * * *   # a cada meia hora
*/5 * * * *  # a cada 5 minutos
15,45 * * * * # aos 15 e 45 minutos
0-30 * * * * # minutos 0 a 30 (cada min)

O primeiro campo controla o minuto (0-59). 0 executa no início da hora. */5 executa de 5 em 5 minutos. É o campo mais usado para tarefas frequentes. Valores válidos: 0 a 59.

Campo hora
# Hora (0-23, formato 24h)
0 3 * * *      # às 03:00
0 15 * * *     # às 15:00
0 9,12,18 * * * # às 09h, 12h e 18h
0 9-17 * * *   # de hora a hora, 09h às 17h
0 */6 * * *    # a cada 6 horas (0h,6h,12h,18h)

O segundo campo define a hora (0-23). Formato 24h sem AM/PM. 9-17 cobre horário laboral. */6 executa a cada 6 horas. Combine com minuto 0 para horas exactas.

Campos dia e mês
# Dia do mês (1-31)
0 0 1 * *      # dia 1 de cada mês
0 0 15 * *     # dia 15 de cada mês
0 0 1,15 * *   # dias 1 e 15

# Mês (1-12 ou JAN-DEC)
0 0 1 1 *      # 1 de Janeiro
0 0 1 6,12 *   # Junho e Dezembro
0 0 * 1-3 *    # Jan, Fev e Mar (diário)

O terceiro campo é o dia do mês (1-31). O quarto é o mês (1-12 ou nomes JAN-DEC). Se dia for *, executa todos os dias. Cuidado: dia 31 não existe em todos os meses.

Operadores e Valores


5 cards
Asterisco (todos)
* * * * *    # cada minuto (todos os valores)
0 * * * *    # minuto 0 de CADA hora
0 0 * * *    # meia-noite de CADA dia
0 0 1 * *    # dia 1 de CADA mês

# * = "qualquer valor" para esse campo
# Equivale ao intervalo completo:
# * no minuto = 0-59
# * na hora   = 0-23

O * significa "todos os valores possíveis" para o campo. No minuto equivale a 0-59, na hora a 0-23. É o valor por defeito. Use quando não quer restringir esse campo específico.

Atalhos especiais
@reboot     # ao iniciar o sistema
@yearly     # = 0 0 1 1 *   (1 Jan, 00:00)
@annually   # = @yearly
@monthly    # = 0 0 1 * *   (dia 1, 00:00)
@weekly     # = 0 0 * * 0   (domingo, 00:00)
@daily      # = 0 0 * * *   (meia-noite)
@midnight   # = @daily
@hourly     # = 0 * * * *   (início da hora)

# Mais legíveis que a sintaxe numérica

Os atalhos @daily, @hourly etc. substituem expressões numéricas. @reboot executa uma vez ao arrancar o sistema. São mais legíveis e menos propensos a erros. Nem todos os sistemas suportam todos os atalhos — verifique a documentação.

Vírgula (lista)
# Lista de valores separados por vírgula
0 9,12,15 * * *    # às 09h, 12h e 15h
0 0 1,15 * *       # dias 1 e 15
0 9 * * 1,3,5      # seg, qua e sex
0 0 * 1,4,7,10 *   # Jan, Abr, Jul, Out

# Pode combinar com intervalos:
0 9-12,14-17 * * * # 9h-12h e 14h-17h

A vírgula cria uma lista de valores discretos. 9,12,15 executa nessas 3 horas. Pode misturar com intervalos: 9-12,14-17. Sem espaços após a vírgula. Ideal para horários específicos múltiplos.

Hífen (intervalo)
# Intervalo contínuo de valores
0 9-17 * * *     # de hora a hora, 09h às 17h
0 0 * * 1-5      # segunda a sexta
*/10 8-18 * * *  # a cada 10min, 08h às 18h
0 0 1-15 * *     # primeiros 15 dias do mês

# O intervalo é inclusivo:
# 9-17 = 9,10,11,12,13,14,15,16,17

O hífen define um intervalo contínuo e inclusivo. 9-17 inclui 9, 10, 11... até 17. 1-5 no dia da semana = seg a sex. Combine com / para passos dentro do intervalo: 8-18/2 = horas pares.

Barra (passo)
# Passo: executa a cada N unidades
*/5 * * * *      # a cada 5 minutos
*/15 * * * *     # a cada 15 minutos
0 */2 * * *      # a cada 2 horas
0 */6 * * *      # a cada 6 horas
0 9-17/2 * * *   # 9h, 11h, 13h, 15h, 17h

# */N = "a cada N" a partir do mínimo
# Equivale a: 0-N/max com passo N

A barra define o passo (frequência). */5 = a cada 5 unidades. */15 no minuto = 0, 15, 30, 45. Pode combinar com intervalo: 9-17/2 = horas ímpares entre 9 e 17. Muito usado para tarefas periódicas.

Exemplos Práticos


5 cards
Backups diários
# Backup da BD às 02:30 todos os dias
30 2 * * * /usr/bin/mysqldump -u root minha_bd > /backups/bd_$(date +\%F).sql

# Backup de ficheiros às 03:00
0 3 * * * tar -czf /backups/site_$(date +\%F).tar.gz /var/www

# Limpar backups com mais de 30 dias
0 4 * * * find /backups -mtime +30 -delete

Backups são o uso mais comum do cron. $(date +\%F) gera nome com data (escape o % com \). Combine backup + limpeza automática. Agende em horário de baixo tráfego (madrugada).

Scripts com PHP e Node
# PHP com caminho absoluto
0 3 * * * /usr/bin/php /var/www/app/cron.php

# Laravel Artisan
* * * * * cd /app && php artisan schedule:run

# Node.js
*/10 * * * * /usr/bin/node /scripts/worker.js

# Python
0 */4 * * * /usr/bin/python3 /scripts/etl.py

# Sempre use caminhos ABSOLUTOS

Sempre use o caminho absoluto do interpretador (/usr/bin/php). O cron não carrega o PATH do utilizador. Para Laravel, o padrão é schedule:run a cada minuto. Use cd se o script depende do directório de trabalho.

Tarefas frequentes
# A cada 5 minutos: verificar fila
*/5 * * * * php /app/artisan queue:work --stop-when-empty

# A cada hora: limpar cache
0 * * * * php /app/artisan cache:clear

# A cada 15 minutos: sync de dados
*/15 * * * * /app/scripts/sync.sh

# A cada minuto: monitorização
* * * * * curl -s https://meu-site.com/health

Tarefas recorrentes usam */N para frequência. */5 = 5 minutos, */15 = 15 minutos. Para Laravel, prefira o schedule interno. curl para health checks simples. Evite tarefas a cada minuto se possível.

Horário laboral
# Relatórios às 09:00 de seg a sex
0 9 * * 1-5 /scripts/relatorio_diario.sh

# Lembrete às 17:30 de seg a sex
30 17 * * 1-5 /scripts/lembrete.sh

# Limpeza de sessão a cada 30min (24/7)
*/30 * * * * php /app/artisan session:gc

# Verificação a cada 2h em dias úteis
0 9-18/2 * * 1-5 /scripts/check.sh

1-5 no dia da semana restringe a seg-sex. Combine com 9-17 na hora para horário laboral. 9-18/2 executa às 9h, 11h, 13h, 15h, 17h. Tarefas de manutenção podem correr 24/7 com * no dia.

Mensais e anuais
# Facturação no dia 1 às 06:00
0 6 1 * * /scripts/facturacao.sh

# Relatório trimestral (Jan,Abr,Jul,Out)
0 8 1 1,4,7,10 * /scripts/trimestral.sh

# Renovação de certificados (dia 15)
0 3 15 * * certbot renew --quiet

# Aniversário do sistema (1 Jan)
0 0 1 1 * /scripts/aniversario.sh

Tarefas mensais fixam o dia do mês: 0 6 1 * * = dia 1 às 6h. Trimestral usa lista de meses: 1,4,7,10. certbot renew é um caso clássico mensal. Para "último dia do mês", use lógica no script.

Gestão e CLI


4 cards
Comandos crontab
crontab -e     # editar crontab do utilizador
crontab -l     # listar entradas actuais
crontab -r     # remover TODAS as entradas
crontab -u user -e  # editar de outro user

# Editar com editor específico:
EDITOR=nano crontab -e
EDITOR=vim crontab -e

crontab -e abre o editor para gerir jobs. -l lista sem editar. -r apaga tudo (cuidado!). -u para outro utilizador (requer root). O editor é definido por EDITOR ou VISUAL.

Ficheiros do sistema
/etc/crontab          # crontab do sistema
/etc/cron.d/          # jobs de pacotes
/var/spool/cron/      # crontabs de utilizadores

# Directórios de execução automática:
/etc/cron.hourly/     # scripts a cada hora
/etc/cron.daily/      # scripts diários
/etc/cron.weekly/     # scripts semanais
/etc/cron.monthly/    # scripts mensais

# Basta colocar um script executável lá

/etc/crontab é o ficheiro global do sistema. /etc/cron.d/ para jobs de pacotes. Os directórios cron.daily/ etc. executam scripts automaticamente — basta copiar um ficheiro executável. Mais simples que editar crontab para tarefas standard.

Permissões e controlo
# Permitir utilizadores:
/etc/cron.allow    # whitelist (só estes)
/etc/cron.deny     # blacklist (todos excepto)

# Verificar serviço:
systemctl status cron
systemctl restart cron
systemctl enable cron    # arranque automático

# Logs (Ubuntu/Debian):
grep CRON /var/log/syslog

cron.allow e cron.deny controlam quem pode usar cron. Se cron.allow existir, só listados podem. O serviço chama-se cron (Debian) ou crond (RHEL). Logs em /var/log/syslog filtrando CRON.

Redireccionar output
# Guardar output em ficheiro:
0 3 * * * /script.sh >> /var/log/job.log 2>&1

# Descartar output (silenciar):
0 3 * * * /script.sh > /dev/null 2>&1

# Só guardar erros:
0 3 * * * /script.sh 2>> /var/log/erros.log

# Enviar por email (se MAILTO definido):
MAILTO=admin@exemplo.com
0 3 * * * /script.sh

Por defeito, o cron envia output por email. >> /ficheiro 2>&1 guarda stdout e stderr. > /dev/null 2>&1 silencia tudo. 2>> só captura erros. MAILTO define destinatário dos emails. Sempre redireccione para evitar emails indesejados.

Avançado e Boas Práticas


4 cards
Variáveis de ambiente
# Definir no topo do crontab:
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
MAILTO=admin@exemplo.com
HOME=/home/deploy

# Ou inline no comando:
0 3 * * * DB_PASS=secret /script.sh

# Carregar env de ficheiro:
0 3 * * * . /home/user/.env && /script.sh

O cron tem um PATH mínimo — defina explicitamente. SHELL define o interpretador. MAILTO controla emails. Use . /ficheiro.env para carregar variáveis. Sem isto, comandos como node ou composer não são encontrados.

Evitar sobreposição
# flock: impede execução simultânea
*/5 * * * * flock -n /tmp/job.lock /script.sh

# Alternativa com PID file:
* * * * * [ ! -f /tmp/job.pid ] && /script.sh & echo $! > /tmp/job.pid

# systemd timer (alternativa moderna):
# /etc/systemd/system/job.timer
# [Timer]
# OnCalendar=*:0/5

flock -n cria lock file — se já estiver a correr, não executa. Essencial para tarefas que demoram mais que o intervalo. Sem lock, múltiplas instâncias podem corromper dados. systemd timers são a alternativa moderna com melhor controlo.

Debugging e logs
# Verificar se o cron está activo:
systemctl status cron
pgrep cron

# Logs em tempo real:
tail -f /var/log/syslog | grep CRON

# Testar expressão antes de agendar:
# Use: crontab.guru (online)

# Script de teste com timestamp:
* * * * * echo "$(date): correu" >> /tmp/cron_test.log

# Remover após confirmar:
# crontab -e → apagar linha de teste

tail -f /var/log/syslog | grep CRON mostra execuções em tempo real. crontab.guru explica expressões visualmente. Para debug, agende * * * * * com echo e verifique o log. Problemas comuns: PATH errado e permissões.

Boas práticas
# 1. Caminhos absolutos SEMPRE
0 3 * * * /usr/bin/php /app/script.php

# 2. Redireccionar output
0 3 * * * /script.sh >> /var/log/job.log 2>&1

# 3. Usar flock para tarefas longas
*/5 * * * * flock -n /tmp/j.lock /script.sh

# 4. Comentar cada entrada
# Backup diário da base de dados
30 2 * * * /scripts/backup.sh

# 5. Testar o comando manualmente antes

Sempre use caminhos absolutos — o cron não herda o PATH. Redireccione output para logs. Use flock para evitar sobreposição. Comente cada job para manutenção futura. Teste o comando manualmente antes de agendar. Prefira scripts a comandos inline longos.