Infraestrutura & Ferramentas

Scheduler

Agendamento de tarefas (cron).

Agendamento — Schedule

Agendamento de tarefas 100% nativo do illuminate/console Scheduling. Um único cron entry no servidor (* * * * *) é suficiente — o Schedule controla os horários internamente, sem precisar de uma entrada de cron por tarefa.

Como funciona

cron (a cada minuto)
    └── php artisan schedule:run
            └── carrega as tarefas definidas em routes/console.php
            └── verifica quais estão no horário
                ├── sim → executa (com mutex se ->withoutOverlapping())
                └── não → ignora

Definindo tarefas

Tarefas vivem em routes/console.php — sem app/Console/Kernel.php (estilo Laravel 11+): o arquivo é carregado automaticamente e usa o facade Schedule direto.

use Illuminate\Support\Facades\Schedule;

// Chamar uma closure
Schedule::call(function () {
    SystemSession::where('expires_at', '<', now())->delete();
})->dailyAt('03:00')->name('limpar-sessoes')->withoutOverlapping();

// Rodar um comando artisan (inclusive os seus, registrados via make:command)
Schedule::command('relatorio:mensal')->monthlyOn(1, '06:00');

// Despachar um Job na fila
Schedule::call(fn () => RelatorioVendasJob::dispatch())
    ->weeklyOn(1, '07:00')
    ->name('relatorio-vendas');

// Executar um comando de shell
Schedule::exec('sh /home/user/scripts/backup.sh')
    ->dailyAt('02:30')
    ->name('backup-banco')
    ->appendOutputTo('/home/user/logs/backup.log');

O próprio framework já agenda 3 tarefas internas (drenagem do MadTrace e limpeza de exports do grid) — veja o topo de routes/console.php. O MadBuilder injeta as tarefas do seu projeto entre os marcadores >>> MADBUILDER:SCHEDULE / <<< MADBUILDER:SCHEDULE — não edite essa faixa à mão.


Frequências disponíveis

Por minuto / hora

->everyMinute()              // a cada 1 minuto
->everyTwoMinutes()          // a cada 2 minutos
->everyFiveMinutes()         // a cada 5 minutos
->everyTenMinutes()          // a cada 10 minutos
->everyFifteenMinutes()      // a cada 15 minutos
->everyThirtyMinutes()       // a cada 30 minutos
->hourly()                   // toda hora no minuto 0
->hourlyAt(15)                // toda hora no minuto 15
->everyTwoHours()            // a cada 2 horas
->everySixHours()            // a cada 6 horas

Por dia / semana / mês

->daily()                    // todo dia à meia-noite
->dailyAt('08:30')           // todo dia às 08:30
->twiceDaily(6, 18)          // duas vezes por dia: 06:00 e 18:00
->weekdays()                 // apenas dias úteis (seg-sex)
->weekends()                 // apenas fins de semana
->mondays()                  // apenas segundas (...tuesdays(), wednesdays() etc.)
->weekly()                   // toda segunda à meia-noite
->weeklyOn(3, '10:00')       // toda quarta às 10:00
->monthly()                  // todo dia 1 do mês à meia-noite
->monthlyOn(15, '12:00')     // todo dia 15 às 12:00
->quarterly()                // primeiro dia de cada trimestre
->yearly()                   // 1 de janeiro à meia-noite

Cron expression customizada

->cron('0 9 * * 1-5')        // 09:00 em dias úteis
->cron('*/10 8-18 * * *')    // a cada 10min entre 8h e 18h

Modificadores de comportamento

// Evita sobreposição (mutex nativo do Laravel, via cache lock)
->withoutOverlapping()
->withoutOverlapping(10)      // aguarda até 10min pelo lock antes de pular

// Roda em background — o scheduler não espera o processo terminar
->runInBackground()

// Restrições de horário
->between('8:00', '17:00')
->unlessBetween('23:00', '6:00')

// Condicional
->when(fn () => date('j') === '1')      // só roda se a condição for true
->skip(fn () => app()->isDownForMaintenance())  // nunca roda se for true

// Output
->appendOutputTo('/caminho/log.log')
->emailOutputTo('time@empresa.com')     // exige MAIL_MAILER configurado

CLI

# Ver todas as tarefas com próxima execução
php artisan schedule:list

# Executar tarefas devidas agora (o que o cron chama)
php artisan schedule:run

# Modo desenvolvimento — loop em foreground, substitui o cron localmente
php artisan schedule:work

# Rodar uma tarefa específica agora, fora do horário (debug)
php artisan schedule:test

Cron no servidor

A ÚNICA entrada necessária — o Laravel decide internamente o que está no horário:

Linux (crontab -e)

* * * * * cd /var/www/html && php artisan schedule:run >> /dev/null 2>&1

cPanel (shared hosting)

No painel Cron Jobs, adicionar:

* * * * * /usr/local/bin/php /home/SEU_USER/public_html/artisan schedule:run >> /home/SEU_USER/logs/scheduler.log 2>&1

Desenvolvimento local

# Substitui o cron localmente (loop em foreground)
php artisan schedule:work

Pausar tarefas sem editar código

Tarefas registradas em routes/console.php podem ser pausadas/reativadas em runtime, sem deploy, via a tela Central de Comando → Agendamentos (admin). O mecanismo: uma linha em mad_sys_schedule_override com active = 0 faz schedule:run/schedule:work pularem aquela tarefa (->skip(...) injetado automaticamente em todo evento do Schedule, casando pelo nome do comando artisan). Sem linha de override → tarefa roda normalmente (fail-open: se a tabela não existir, nada é pausado). A conexão consultada é config('mad.schedule.connection', 'iam').

A mesma tela mostra última execução e status de cada tarefa (lidos de mad_sys_schedule_log), além de um botão "Executar agendador agora" para forçar um schedule:run fora do cron — útil pra QA.

Veja também

  • Filas (Queue) — para tarefas agendadas que disparam Jobs em background em vez de rodar inline no processo do scheduler.