Tarefas cron
Execute um comando ou uma requisição HTTP conforme um agendamento. Leia “Onde o comando é executado” antes da sua primeira tarefa: uma tarefa agendada não é executada dentro do contêiner em execução do seu aplicativo, mas em um contêiner descartável que recebe as mesmas variáveis.
Criando um Cron Job
As tarefas agendadas são gerenciadas na página Tarefas agendadas do painel, ou com sh0 cron. Uma tarefa normalmente está vinculada a uma aplicação.
- Abra Tarefas agendadas na barra lateral e clique em Criar tarefa.
- Nome -- um rótulo, por exemplo
nightly-report. - Aplicação -- a aplicação à qual a tarefa pertence. Sem aplicação, apenas comandos HTTP são aceitos (veja abaixo).
- Agendamento -- uma expressão cron de 5 campos, avaliada em UTC.
- Comando -- uma requisição HTTP (
curl,wgetou apenas uma URL), ou um programa a executar num contêiner. - Opcional: uma Imagem do contêiner (vazia = a imagem da aplicação) e um Tempo limite (segundos), 300 por padrão. Depois, crie a tarefa.
O mesmo pela CLI, num servidor onde estes comandos foram executados:
$ sh0 cron create --app my-api --name nightly-report \
--schedule "0 3 * * *" \
--command "curl -s -X POST https://api.example.com/internal/report"
Cron job 'nightly-report' created (id: 72173a56-1962-47dc-88e5-2a276ef3bfcc)
$ sh0 cron trigger 72173a56-1962-47dc-88e5-2a276ef3bfcc
Cron job 'nightly-report' triggered.
$ sh0 cron runs 72173a56-1962-47dc-88e5-2a276ef3bfcc
RUN ID STATUS EXIT DURATION STARTED
----------------------------------------------------------------------------------------------------
9e329bc7-01c5-41ec-9eb5-5ab745fde533 success 0 295ms 2026-10-02 02:33:23Onde o comando é executado
O sh0 escolhe o modo de execução a partir do comando e das configurações da tarefa, nesta ordem:
- Requisição HTTP -- um comando que começa com
curlouwget, ou uma URL sozinha, não é executado por um shell: o sh0 envia a requisição ele mesmo, a partir do servidor, com limite de 30 segundos.-X,-He-dsão respeitados. Um status de resposta de 400 ou mais marca a execução como falha. Para uma tarefa vinculada a um aplicativo, um nome interno do seu projeto (my-api.internal, oumy-apisozinho) é resolvido para esse serviço. - Imagem do aplicativo -- qualquer outro comando é executado em um contêiner novo e descartável iniciado a partir da imagem atual do aplicativo, com um usuário não root, na rede do sh0 e na rede do seu projeto. Não é o seu contêiner em execução: os arquivos gravados pelo aplicativo em tempo de execução não estão lá, e o contêiner é removido após a execução.
- Imagem explícita -- se Imagem do contêiner estiver preenchida, o contêiner descartável parte dessa imagem.
- Sem aplicação nem imagem -- um comando que não seja HTTP é recusado no momento da execução. O sh0 nunca executa um comando agendado no host.
Medido em um aplicativo Node.js com GREETING definido no aplicativo e REGION no projeto: a tarefa env mostra as duas, ao lado das variáveis embutidas na imagem.
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=0.0.0.0
REGION=eu431
GREETING=hello431
NODE_VERSION=22.23.3
YARN_VERSION=1.22.22
PORT=3000
HOME=/home/nodeGREETING e REGION estão presentes. A linha HOME=/home/node mostra o usuário não root.
Regras do comando
Um comando é um único programa com os seus argumentos. O sh0 verifica-o na criação da tarefa:
- Sem shell. Os caracteres
;|&><e a crase,$(e as quebras de linha são recusados. Não há pipes, encadeamentos&&nem expansão de variáveis. - As aspas só contam nas requisições HTTP. Num contêiner, o comando é dividido nos espaços:
sh -c "echo hi"não faz o que um shell faria. Nas requisições HTTP as aspas são respeitadas, por isso-H "Authorization: Bearer …"funciona. - Os redirecionamentos são removidos em vez de recusados:
> /dev/null,2>/dev/null,&> /dev/nulle2>&1são retirados antes da verificação, de modo que uma linha copiada de um crontab é aceita. - No máximo 4096 caracteres.
$ sh0 cron create --app my-api --name cleanup --schedule "0 3 * * *" --command "env | grep X"
Error: Invalid command: Command contains forbidden character '|'. Use simple commands without shell operators. (VALIDATION_ERROR)Tarefas que precisam do banco de dados ou de segredos
Uma tarefa vinculada a um aplicativo vê as variáveis dele e resolve os nomes internos do seu projeto, então um comando como python manage.py cleanup lê a mesma DATABASE_URL e alcança o mesmo db.internal. Quando o trabalho pertence ao aplicativo em execução, restam outras duas opções:
- Um endpoint HTTP. Exponha a tarefa como uma rota do seu aplicativo, protegida por um token, e deixe a tarefa agendada chamá-la pelo nome interno. O trabalho é executado dentro do aplicativo em execução, com a conexão ao banco e os segredos dele.
- Ou agende dentro da aplicação, com o agendador do seu framework (por exemplo Celery beat, node-cron ou o agendador do Laravel), quando a tarefa não deve ser acessível por HTTP de forma alguma.
curl -s -X POST -H "Authorization: Bearer <token>" http://my-api.internal:3000/internal/cleanupmy-api.internal (ou my-api) apenas entre os serviços em execução do projeto da tarefa. Um nome que não corresponde a nenhum serviço em execução falha com uma mensagem explícita; um aplicativo fora de qualquer projeto, ou em um nó remoto, deve ser chamado pela URL pública. O token fica em claro no comando da tarefa, visível para quem puder ler a tarefa: não lhe dê nenhum outro uso.Sintaxe de Expressão Cron
O sh0 usa expressões cron padrão de 5 campos. Cada campo representa uma unidade de tempo:
┌───────────── minute (0-59)
│ ┌───────────── hour (0-23)
│ │ ┌───────────── day of month (1-31)
│ │ │ ┌───────────── month (1-12)
│ │ │ │ ┌───────────── day of week (0-6, Sunday = 0)
│ │ │ │ │
* * * * *| Símbolo | Significado | Exemplo |
|---|---|---|
| * | Todo valor | * * * * * = a cada minuto |
| , | Lista de valores | 0 8,12,18 * * * = 8h, 12h, 18h |
| - | Intervalo | 0 9-17 * * * = a cada hora das 9h às 17h |
| / | Passo | */15 * * * * = a cada 15 minutos |
Padrões Comuns
# Every minute
* * * * *
# Every 5 minutes
*/5 * * * *
# Every hour at minute 0
0 * * * *
# Every day at midnight
0 0 * * *
# Every day at 3:30 AM
30 3 * * *
# Every Monday at 9:00 AM
0 9 * * 1
# First day of every month at midnight
0 0 1 * *
# Every weekday (Mon-Fri) at 6:00 AM
0 6 * * 1-50 3 * * * roda às 03:00 UTC. O agendador procura tarefas pendentes a cada 60 segundos, então uma execução pode começar até um minuto depois do horário.Histórico de Execução e Logs
Cada execução é registrada com o status (success, failed ou timeout), código de saída, duração, horários de início e fim, e saída. No painel, abra Histórico de execuções numa tarefa e exiba a saída de uma execução. Pela CLI: sh0 cron runs <id>.
Habilitando e Desabilitando Jobs
- Desativar interrompe as execuções agendadas sem apagar a tarefa nem o histórico; Ativar retoma-as.
- Executar agora (ou
sh0 cron trigger <id>) inicia uma execução imediatamente, qualquer que seja o agendamento. - Excluir uma tarefa (
sh0 cron delete <id>) também exclui o histórico.
Tempos limite, sobreposição e limites
- Tempo limite -- 300 segundos por padrão (
--timeoutna CLI). Uma execução que o ultrapassa é registrada com o statustimeoute a mensagem “Job timed out after Ns”. - Sobreposição -- enquanto uma execução de uma tarefa está em andamento, o agendador não inicia outra. A ocorrência ignorada não fica registrada no histórico.
- 50 tarefas por aplicação.
- Sem novas tentativas nem notificações de falha. Uma execução com falha não é repetida e não envia alerta: consulte o histórico, ou faça o endpoint chamado pela tarefa relatar as próprias falhas.