Um cron job é uma tarefa que roda automaticamente em um agendamento de tempo; o Cloud Code agendado aplica a ideia a funções serverless. A linhagem vai do Unix Version 7, passando pelo Vixie cron (1987), até os agendadores de plataforma de hoje — e o modelo quase não mudou: um daemon acorda a cada minuto, lê uma tabela de linhas agendamento + comando — a crontab — e dispara o que casar. O que mudou foi tudo em volta do modelo: onde o relógio mora, o que acontece quando uma execução falha, e se alguém percebe.
Principais pontos
| Pergunta | Resposta |
|---|---|
| A sintaxe | Cinco campos — minuto · hora · dia do mês · mês · dia da semana |
| O piso | Granularidade de um minuto; segundos exigem outro agendador |
| As pegadinhas | Horário de verão pula e duplica · a regra OR entre dia-do-mês e dia-da-semana |
| A lacuna de confiabilidade | Cron clássico: sem retry, sem catch-up, sem cluster, falha silenciosa |
| A forma moderna | Agendamento como config de plataforma sobre uma função — relógio, logs e retries gerenciados |
Cron em uma tela
┌ minuto (0–59) ┌ hora (0–23) ┌ dia do mês (1–31) ┌ mês ┌ dia da semana (0–7)
* * * * * comando
0 2 * * * todo dia às 02:00 */15 * * * * a cada 15 minutos
0 9 * * 1-5 dias úteis às 09:00 0 6,18 * * * às 06:00 e às 18:00
0 0 1,15 * * nos dias 1º e 15 @daily = 0 0 * * *
@reboot uma vez quando o daemon sobe @hourly = 0 * * * *
crontab -e edita sua tabela crontab -l lista a tabela
crontab -ri remove (com confirmação — o -r puro apaga tudo, sem perguntar)
O equivalente moderno — o job em código, o agendamento em um dashboard, o cliente só lendo os resultados:
// JavaScript — Cloud Code (cloud/main.js)
// A scheduled job: defined in code, scheduled in the dashboard
Parse.Cloud.job('nightlyReport', async (request) => {
const since = new Date(Date.now() - 24 * 60 * 60 * 1000);
// Idempotent by date key: a rerun overwrites tonight's report, not duplicates
const existing = await new Parse.Query('DailyReport')
.equalTo('runDate', dateKey(new Date()))
.first({ useMasterKey: true });
const report = existing ?? new Parse.Object('DailyReport');
report.set('runDate', dateKey(new Date()));
report.set('summary', await summarizeOrdersSince(since));
await report.save(null, { useMasterKey: true });
request.message('Report written'); // shows in the dashboard's job status
}); // Flutter / Dart — Back4app Flutter SDK
// Clients consume what the schedule produces — no crontab in sight
final query = QueryBuilder<ParseObject>(ParseObject('DailyReport'))
..orderByDescending('runDate')
..setLimit(1);
final latest = (await query.query()).results?.first as ParseObject?;
print(latest?.get<String>('summary'));
// The report exists because a scheduled Cloud Job ran at 02:00 UTC —
// defined in code, scheduled in the dashboard, logged by the platform. // iOS / Swift — Back4app Swift SDK
// Clients consume what the schedule produces — no crontab in sight
let latest = try await DailyReport.query()
.order([.descending("runDate")])
.first()
print(latest.summary ?? "")
// The report exists because a scheduled Cloud Job ran at 02:00 UTC —
// defined in code, scheduled in the dashboard, logged by the platform. // Android / Kotlin — Back4app Android SDK
// Clients consume what the schedule produces — no crontab in sight
val query = ParseQuery.getQuery<ParseObject>("DailyReport")
query.orderByDescending("runDate")
query.limit = 1
val latest = query.find().firstOrNull()
println(latest?.getString("summary"))
// The report exists because a scheduled Cloud Job ran at 02:00 UTC —
// defined in code, scheduled in the dashboard, logged by the platform. As pegadinhas que a man page conhece
Quatro semânticas da crontab(5) que surpreendem quase todo mundo. A regra OR: quando tanto dia-do-mês quanto dia-da-semana estão restritos, o job dispara quando qualquer um casa — 0 0 13 * 5 roda todo dia 13 e toda sexta-feira, não apenas nas sextas-feiras 13. Horário de verão, ao pé da letra: jobs agendados na “hora que some” da virada do relógio nunca rodam; horários que ocorrem duas vezes na volta rodam duas vezes — agende em UTC, mantenha trabalho crítico fora da madrugada local. Passos reiniciam na borda do campo: */90 no campo do minuto não pode significar “a cada 90 minutos” — o contador zera a cada hora; intervalos quebrados de verdade exigem um agendador de verdade. O piso do minuto: o daemon varre uma vez por minuto; qualquer coisa mais fina é trabalho de outra ferramenta.
A lacuna de confiabilidade
O cron clássico é um agendador, não um sistema de confiabilidade, e a lacuna tem um formato: sem retries (uma execução que falhou é uma execução que falhou); sem catch-up (uma máquina dormindo às 02:00 pula a execução — o anacron e a opção de persistência dos timers do systemd existem exatamente para isso); sem história de cluster (dois servidores com a mesma crontab rodam tudo em dobro; um servidor só é um ponto único de falha); falha silenciosa (a saída vai por mail para uma conta local que ninguém lê). Agendadores modernos respondem a cada lacuna com política nomeada: políticas de misfire (o fire-now vs. skip do Quartz), políticas de concorrência (o allow/forbid/replace do Kubernetes para execuções sobrepostas) e semântica de skip por deadline — documentando honestamente que agendamento distribuído é aproximadamente uma vez: uma execução pode, vez ou outra, duplicar ou não disparar. O que leva à disciplina que os dois mundos compartilham: jobs agendados precisam ser idempotentes — chaveados pelo seu período (o relatório das abas de código, chaveado pela data), para que uma reexecução sobrescreva em vez de duplicar, e uma execução perdida seja recuperável rodando atrasada.
Cron clássico vs. timers do systemd vs. agendadores distribuídos vs. funções agendadas
| Cron clássico | Timers do systemd | Distribuído (estilo Quartz/K8s) | Funções agendadas na nuvem | |
|---|---|---|---|---|
| Mora em | Na crontab de uma máquina | Uma máquina, unit files | Um cluster | Config de plataforma sobre uma função |
| Catch-up | Nenhum (o anacron remenda) | Persistent=true | Políticas de misfire | Política da plataforma |
| Sobreposição | Inicia outra cópia | Serializado por unit | allow / forbid / replace | Política da plataforma |
| Retries | Nenhum | Regras de restart do serviço | Configurável | Embutido |
| Visibilidade de falha | Mail local, não lido | journald | Objetos de status do job | Status + logs no dashboard |
| Servidor para manter vivo | Sim — e ele é o SPOF | Sim | O cluster | Não |
De olho nos agendamentos
Falha agendada é a falha mais quieta da computação: um job que nunca disparou emite nada — nenhuma exceção, nenhuma linha de log, nenhum e-mail — porque nada rodou. O padrão que resolve inverte o alarme: monitoramento por heartbeat — o job pinga uma URL ao completar com sucesso, o monitor espera o ping dentro de um período de tolerância, e a ausência dispara o alerta. Combine com a higiene mundana que o cron clássico nunca teve: duração das execuções acompanhada ao longo do tempo (o relatório que levava 4 minutos no mês passado e 40 hoje à noite está te contando algo), saída capturada em logs de verdade em vez de mail local, e o inventário de agendamentos documentado — porque uma crontab espalhada por cinco servidores é como as organizações descobrem jobs que esqueceram que rodavam.
Casos de uso comuns
- Relatórios e resumos — o rollup noturno que as abas de código esboçam: agregar, gravar, notificar.
- Limpeza e expiração — varreduras de TTL, poda de órfãos, passadas de expiração de sessões e tokens.
- Sincronização de dados — pulls periódicos de sistemas de terceiros que não oferecem webhooks.
- Lembretes e reengajamento — envios baseados em tempo: fim de trial, carrinhos abandonados, avisos de renovação.
- Saúde e reconciliação — a auditoria agendada que pega o que os caminhos orientados a eventos perderam.
Qual agendador você deveria usar? Matriz de decisão
| Situação | Use |
|---|---|
| Uma máquina Linux que você já opera | Cron clássico — com locks e um heartbeat |
| Máquinas intermitentes ou tipo laptop | anacron / timers do systemd com persistência |
| Um cluster que você já roda | O controlador nativo de jobs agendados dele |
| Backend de app em um BaaS | Cloud Jobs agendados — sem servidor, logs incluídos |
| Intervalos abaixo do minuto ou quebrados | Um agendador ou fila de verdade, não aritmética de crontab |
| Trabalho de evento rotulado errado como agendado | A fila de jobs — o cron apenas a alimenta |
Limitações e trade-offs
- Gatilhos de tempo dizem quando, não se. Um agendamento dispara havendo trabalho ou não; triggers orientados a eventos e filas servem ao trabalho que chega irregularmente.
- Aproximadamente-uma-vez é o contrato honesto. Mesmo agendadores gerenciados ocasionalmente duplicam ou pulam; idempotência é responsabilidade do job em todo lugar.
- Fuso horário é decisão de política. Agendamentos em UTC sobrevivem ao horário de verão; agendamentos em hora local servem humanos — escolha deliberadamente, documente em voz alta.
- Frequência tem piso e preço. Nível de minuto no cron clássico, pisos dependentes de plataforma nos demais; polling via cron em alta frequência costuma ser uma queue fantasiada de relógio.
- Agendamentos se acumulam em silêncio. Todo job noturno “temporário” é permanente até ser inventariado; o dashboard que lista todos é um recurso subestimado.
Cloud Code Agendado no Back4app
O Back4app é uma plataforma open-source de Backend as a Service (BaaS) que combina banco de dados gerenciado, APIs REST e GraphQL geradas automaticamente, autenticação, armazenamento de arquivos e funções serverless com Cloud Code. Agendar aqui é a coluna moderna da tabela comparativa tornada concreta: defina Parse.Cloud.job no Cloud Code — o relatório noturno das abas de código, idempotente por chave de data, acesso com master key para a agregação entre usuários — e então agende no painel de Background Jobs do dashboard: nome do job, horário de início, recorrência, sem sintaxe de crontab e sem servidor em cuja crontab ele moraria. Execuções, status e erros caem nos logs do servidor e no painel de jobs — a coluna de visibilidade de falha respondida por padrão — e as disciplinas com que este artigo termina continuam suas por design: chaveie os jobs pelo período, mantenha-os idempotentes, e deixe um heartbeat confirmar que o relógio da plataforma e a sua lógica concordaram hoje à noite, como toda noite.
Perguntas frequentes
O que é um cron job?
É uma tarefa agendada para rodar automaticamente em horários ou intervalos fixos — classicamente pelo daemon cron em sistemas Unix lendo uma crontab e, por extensão, qualquer job disparado por tempo em qualquer plataforma. O nome vem de chronos, "tempo" em grego.
O que significam os cinco campos de uma expressão cron?
Minuto (0–59), hora (0–23), dia do mês (1–31), mês (1–12) e dia da semana (0–7, onde tanto 0 quanto 7 são domingo), seguidos do comando. Asterisco significa todos os valores; vírgulas listam, hífens definem intervalos, barras definem passos.
O que acontece se a máquina estiver desligada no horário agendado?
O cron clássico simplesmente pula a execução — não existe recuperação. É por isso que o anacron existe para máquinas ligadas intermitentemente, que os timers do systemd oferecem uma opção de persistência, e que agendadores modernos tratam a política de catch-up como configuração explícita, não como surpresa.
Como o cron lida com o horário de verão?
Mal, por padrão: segundo o próprio manual, jobs agendados na "hora que some" da virada nunca rodam, e horários que ocorrem duas vezes na volta do relógio rodam duas vezes. O conselho de sempre: agende em UTC e mantenha jobs críticos fora da janela local de 00:00–03:00.
E se um job ainda estiver rodando quando a próxima execução começar?
O cron clássico alegremente inicia uma segunda cópia — e uma terceira. Sobreposição exige uma resposta explícita: um arquivo de lock que faz a execução atrasada pular a vez, ou as políticas formalizadas dos agendadores modernos — permitir, proibir ou substituir a instância em execução.
Como sei quando um cron job falha?
Por padrão, você não sabe — a saída vai para uma caixa de mail local que ninguém lê, e um agendamento que nunca disparou não produz erro algum, porque nada rodou. O padrão que resolve: monitoramento por heartbeat — o job pinga uma URL ao ter sucesso, e a ausência do ping é o que dispara o alarme.
O cron pode rodar um job mais de uma vez por minuto?
Não — um minuto é o piso do cron clássico; o daemon acorda, varre e dispara por minuto. Granularidade de segundos exige outro agendador: expressões de seis campos no estilo Quartz, um loop dentro de um serviço, ou uma fila de eventos em vez de um relógio.
Preciso de um servidor para rodar cron jobs?
Não mais. Plataformas serverless prendem o agendamento diretamente a uma função: a plataforma é dona do relógio, dispara o job, registra logs e status e faz retry conforme a política — o agendamento como configuração, e não como um arquivo em uma máquina que você precisa manter viva.