- Introdução
- Definindo Programações
- Configuração de Comandos Artesanais
- Configuração de Trabalhos em Fila de Espera
- Configuração de Comandos em Fila de Espera
- Opções de Frequência de Programação
- Fusos Horários
- Prevenir Sobreposições de Tarefas
- Executar Tarefas Num Servidor
- Tarefas de Fundo
- Modo de Manutenção
- Executar o Scheduler
- Executar o Scheduler Localmente
- Saída da Tarefa
- Gancho da Tarefa
- Introdução
- Definindo Agendamentos
- Agendando Comandos Artisan
- Agendando trabalhos em fila
- Comandos de Programação de Shell
- Opções de Frequência de Programação
- Condições de dias
- Entre restrições de tempo
- Contenções do Teste de Verdade
- Condições ambientais
- Timezones
- Prevenir sobreposições de tarefas
- Running Tasks On One Server
- Tarefas de fundo
- Modo de manutenção
- Running The Scheduler
- Executar o Agendador Localmente
- Saída da Tarefa
- Gancho de Tarefas
- Pingando URLs
Introdução
No passado, você pode ter escrito uma entrada de configuração de cron para cada tarefa que você precisava agendar no seu servidor. No entanto, isto pode rapidamente tornar-se um problema porque o seu agendamento de tarefas não está mais no controle da fonte e você deve SSH no seu servidor para ver as entradas do cron existente ou adicionar entradas adicionais.
O agendador de comandos de Laravel oferece uma nova abordagem para gerenciar tarefas agendadas no seu servidor. O agendador permite que você defina fluente e expressivamente sua agenda de comandos dentro de sua própria aplicação Laravel. Ao usar o agendador, somente uma única entrada cron é necessária no seu servidor. Seu agendamento de tarefas é definido no método app/Console/Kernel.php
do arquivo schedule
. Para ajudá-lo a começar, um exemplo simples é definido dentro do método.
Definindo Agendamentos
Você pode definir todas as suas tarefas agendadas no método schedule
da classe da sua aplicação App\Console\Kernel
. Para começar, vamos dar uma olhada em um exemplo. Neste exemplo, vamos agendar um encerramento para ser chamado todos os dias à meia-noite. Dentro do fechamento vamos executar uma consulta de banco de dados para limpar uma tabela:
<?phpnamespace App\Console;use Illuminate\Console\Scheduling\Schedule;use Illuminate\Foundation\Console\Kernel as ConsoleKernel;use Illuminate\Support\Facades\DB;class Kernel extends ConsoleKernel{ /** * The Artisan commands provided by your application. * * @var array */ protected $commands = ; /** * Define the application's command schedule. * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) { $schedule->call(function () { DB::table('recent_users')->delete(); })->daily(); }}
Além de agendar usando fechamentos, você também pode agendar objetos invocáveis. Objetos invocáveis são classes PHP simples que contêm um método:__invoke
>
$schedule->call(new DeleteRecentUsers)->daily();
Se você gostaria de ver uma visão geral das suas tarefas agendadas e da próxima vez que elas forem agendadas para execução, você pode usar o comando schedule:list
Artisan:
php artisan schedule:list
Agendando Comandos Artisan
Além de agendar fechamentos, você também pode agendar comandos Artisan e comandos do sistema. Por exemplo, você pode usar o método command
para agendar um comando Artisan usando o nome do comando ou a classe.
Ao agendar comandos Artisan usando o nome da classe do comando, você pode passar um array de argumentos de linha de comando adicionais que devem ser fornecidos ao comando quando ele é invocado:
use App\Console\Commands\SendEmailsCommand;$schedule->command('emails:send Taylor --force')->daily();$schedule->command(SendEmailsCommand::class, )->daily();
Agendando trabalhos em fila
O método job
pode ser usado para agendar um trabalho em fila. Este método fornece uma maneira conveniente de agendar trabalhos em fila sem usar o método call
para definir fechamentos para enfileirar o trabalho:
use App\Jobs\Heartbeat;$schedule->job(new Heartbeat)->everyFiveMinutes();
O segundo e terceiro argumentos operacionais podem ser fornecidos ao método job
que especifica o nome da fila e a conexão da fila que deve ser usada para enfileirar o trabalho:
use App\Jobs\Heartbeat;// Dispatch the job to the "heartbeats" queue on the "sqs" connection...$schedule->job(new Heartbeat, 'heartbeats', 'sqs')->everyFiveMinutes();
Comandos de Programação de Shell
O método exec
pode ser usado para emitir um comando ao sistema operacional:
$schedule->exec('node /home/forge/script.js')->daily();
Opções de Frequência de Programação
Já vimos alguns exemplos de como você pode configurar uma tarefa para ser executada em intervalos especificados. Entretanto, há muito mais freqüências de agendamento de tarefas que você pode atribuir a uma tarefa:
Método | Descrição |
---|---|
->cron('* * * * *'); |
Executar a tarefa em um cronograma personalizado |
>->everyMinute();
|
Executar a tarefa a cada minuto |
>->everyTwoMinutes(); > |
Executar a tarefa a cada dois minutos |
>->everyThreeMinutes(); > |
Executar a tarefa a cada três minutos |
->everyFourMinutes(); > |
Executar a tarefa a cada quatro minutos |
->everyFiveMinutes(); |
Executar a tarefa a cada cinco minutos |
->everyTenMinutes(); |
Executar a tarefa a cada dez minutos |
->everyFifteenMinutes(); |
Executar a tarefa a cada quinze minutos |
->everyThirtyMinutes(); > |
Executar a tarefa a cada trinta minutos |
>->hourly(); > |
Executar a tarefa a cada hora |
>->hourlyAt(17);
|
Executar a tarefa a cada 17 minutos depois da hora |
->everyTwoHours(); |
Executar a tarefa a cada duas horas |
->everyThreeHours(); |
Executar a tarefa a cada três horas |
->everyFourHours(); |
Executar a tarefa a cada quatro horas |
->everySixHours(); |
Executar a tarefa a cada seis horas |
->daily(); |
Executar a tarefa todos os dias à meia-noite |
->dailyAt('13:00'); |
Executar a tarefa todos os dias à 13:00 |
->twiceDaily(1, 13); |
Executar a tarefa diariamente à 1:00 & 13:00 |
->weekly(); |
Executar a tarefa todos os domingos à 00:00 |
->weeklyOn(1, '8:00');
|
Executar a tarefa todas as semanas às 8:00 |
->monthly(); |
Executar a tarefa no primeiro dia de cada mês às 00:00:00 |
->monthlyOn(4, '15:00'); |
Executar a tarefa todos os meses no 4º às 15:00 |
->twiceMonthly(1, 16, '13:00'); |
Executar a tarefa mensalmente no 1º e no 16º dia às 13:00:00 |
->lastDayOfMonth('15:00'); |
Executar a tarefa no último dia do mês às 15:00:00 |
->quarterly(); |
Executar a tarefa no primeiro dia de cada trimestre às 00:00 |
->yearly(); |
Executar a tarefa no primeiro dia de cada ano às 00:00 |
->yearlyOn(6, 1, '17:00');
|
Executar a tarefa todos os anos no dia 1 de Junho às 17:00:00 |
->timezone('America/New_York'); |
Definir o fuso horário para a tarefa |
Estes métodos podem ser combinados com restrições adicionais para criar horários ainda mais afinados que só funcionam em certos dias da semana. Por exemplo, você pode programar um comando para executar semanalmente na segunda-feira:
// Run once per week on Monday at 1 PM...$schedule->call(function () { //})->weekly()->mondays()->at('13:00');// Run hourly from 8 AM to 5 PM on weekdays...$schedule->command('foo') ->weekdays() ->hourly() ->timezone('America/Chicago') ->between('8:00', '17:00');
Uma lista de restrições adicionais de horários pode ser encontrada abaixo:
Método | Descrição |
---|---|
->weekdays(); |
Limite a tarefa aos dias da semana |
>->weekends();
|
Limite a tarefa aos fins de semana |
>->sundays(); > |
Limite a tarefa ao domingo |
>->mondays(); > |
Limite a tarefa a segunda-feira |
->tuesdays(); |
Limite a tarefa a terça-feira |
->wednesdays(); |
Limite a tarefa para quarta-feira |
>->thursdays(); > |
Limite a tarefa para quinta-feira |
>->fridays(); > |
Limite a tarefa para sexta-feira |
->saturdays(); |
Limite a tarefa a sábado |
->days(array|mixed); > |
Limite a tarefa a dias específicos |
->between($startTime, $endTime); |
Limite a tarefa a executar entre o início e o fim |
->unlessBetween($startTime, $endTime); |
Limite a tarefa a não executar entre o início e o fim tempos finais |
->when(Closure); |
Limite a tarefa com base num teste de verdade |
->environments($env); |
Limite a tarefa a um teste de verdade ambientes |
Condições de dias
O método days
pode ser usado para limitar a execução de uma tarefa a dias específicos da semana. Por exemplo, você pode programar um comando para executar uma tarefa por hora aos domingos e quartas:
$schedule->command('emails:send') ->hourly() ->days();
Alternativamente, você pode usar as constantes disponíveis na classe Illuminate\Console\Scheduling\Schedule
ao definir os dias em que uma tarefa deve ser executada:
use Illuminate\Console\Scheduling\Schedule;$schedule->command('emails:send') ->hourly() ->days();
Entre restrições de tempo
O método between
pode ser usado para limitar a execução de uma tarefa com base na hora do dia:
$schedule->command('emails:send') ->hourly() ->between('7:00', '22:00');
Simplesmente, o método unlessBetween
pode ser usado para excluir a execução de uma tarefa por um período de tempo:
$schedule->command('emails:send') ->hourly() ->unlessBetween('23:00', '4:00');
Contenções do Teste de Verdade
O método when
pode ser usado para limitar a execução de uma tarefa com base no resultado de um determinado teste de verdade. Em outras palavras, se o fechamento dado retornar true
, a tarefa será executada desde que nenhuma outra condição restritiva impeça a execução da tarefa:
$schedule->command('emails:send')->daily()->when(function () { return true;});
O método skip
pode ser visto como o inverso de when
. Se o método skip
retornar true
, a tarefa agendada não será executada:
$schedule->command('emails:send')->daily()->skip(function () { return true;});
Ao usar métodos encadeados when
, o comando agendado só será executado se todos os métodos when
retornarem condições true
.
Condições ambientais
O método environments
pode ser usado para executar tarefas somente nos ambientes dados (como definido pela variável de ambiente APP_ENV
):
$schedule->command('emails:send') ->daily() ->environments();
Timezones
Usando o método timezone
, você pode especificar que o tempo de uma tarefa agendada deve ser interpretado dentro de um determinado fuso horário:
$schedule->command('report:generate') ->timezone('America/New_York') ->at('2:00')
Se você estiver atribuindo repetidamente o mesmo fuso horário a todas as suas tarefas agendadas, você pode desejar definir um método scheduleTimezone
na sua classe App\Console\Kernel
. Este método deve retornar o fuso horário padrão que deve ser atribuído a todas as tarefas agendadas:
/** * Get the timezone that should be used by default for scheduled events. * * @return \DateTimeZone|string|null */protected function scheduleTimezone(){ return 'America/Chicago';}
{ nota} Lembre-se que alguns fusos horários utilizam o horário de verão. Quando o horário de verão muda, a sua tarefa programada pode ser executada duas vezes ou até mesmo não ser executada de todo. Por este motivo, recomendamos evitar o agendamento de fusos horários quando possível.
Prevenir sobreposições de tarefas
Por padrão, as tarefas agendadas serão executadas mesmo que a instância anterior da tarefa ainda esteja em execução. Para prevenir isto, você pode usar o método withoutOverlapping
:
$schedule->command('emails:send')->withoutOverlapping();
Neste exemplo, o comando emails:send
Artisan será executado a cada minuto se ainda não estiver em execução. O método withoutOverlapping
é especialmente útil se você tiver tarefas que variam drasticamente em seu tempo de execução, impedindo que você preveja exatamente quanto tempo uma determinada tarefa levará.
Se necessário, você pode especificar quantos minutos devem passar antes que o bloqueio “sem sobreposição” expire. Por padrão, o bloqueio expirará após 24 horas:
$schedule->command('emails:send')->withoutOverlapping(10);
Running Tasks On One Server
{note} Para utilizar este recurso, seu aplicativo deve estar usando o driver de cache padrão do seu aplicativo. Além disso, todos os servidores devem estar se comunicando com o mesmo servidor de cache central.
Se o agendador do seu aplicativo estiver sendo executado em vários servidores, você pode limitar um trabalho agendado a ser executado apenas em um único servidor. Por exemplo, assuma que você tem uma tarefa agendada que gera um novo relatório toda sexta-feira à noite. Se o agendador de tarefas estiver sendo executado em três servidores de trabalhadores, a tarefa agendada será executada nos três servidores e gerará o relatório três vezes. Nada bom!
Para indicar que a tarefa deve ser executada em apenas um servidor, use o método onOneServer
ao definir a tarefa agendada. O primeiro servidor a obter a tarefa irá assegurar um bloqueio atômico no trabalho para evitar que outros servidores executem a mesma tarefa ao mesmo tempo:
$schedule->command('report:generate') ->fridays() ->at('17:00') ->onOneServer();
Tarefas de fundo
Por padrão, múltiplas tarefas agendadas ao mesmo tempo serão executadas sequencialmente com base na ordem em que estão definidas no método schedule
. Se você tiver tarefas de longa duração, isto pode fazer com que as tarefas subsequentes comecem muito mais tarde do que o previsto. Se você gostaria de executar tarefas em segundo plano para que todas elas possam ser executadas simultaneamente, você pode usar o método runInBackground
:
$schedule->command('analytics:report') ->daily() ->runInBackground();
{ nota}. O método
runInBackground
só pode ser usado ao agendar tarefas através dos métodoscommand
eexec
.
Modo de manutenção
As tarefas agendadas da sua aplicação não serão executadas quando a aplicação estiver em modo de manutenção, uma vez que não queremos que as suas tarefas interfiram com qualquer manutenção inacabada que possa estar a executar no seu servidor. No entanto, se você quiser forçar uma tarefa a ser executada mesmo em modo de manutenção, você pode chamar o método evenInMaintenanceMode
ao definir a tarefa:
$schedule->command('emails:send')->evenInMaintenanceMode();
Running The Scheduler
Agora aprendemos a definir as tarefas agendadas, vamos discutir como executá-las de fato em nosso servidor. O comando schedule:run
Artisan avaliará todas as suas tarefas agendadas e determinará se elas precisam ser executadas com base na hora atual do servidor.
Então, ao usar o agendador de Laravel, só precisamos adicionar uma única entrada de configuração cron ao nosso servidor que executa o comando schedule:run
a cada minuto. Se você não sabe como adicionar entradas cron ao seu servidor, considere usar um serviço como Laravel Forge que pode gerenciar as entradas cron para você:
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
Executar o Agendador Localmente
Tipicamente, você não adicionaria uma entrada cron do agendador à sua máquina de desenvolvimento local. Em vez disso, você pode usar o comando schedule:work
Artisan. Este comando será executado em primeiro plano e invocará o agendador a cada minuto até terminar o comando:
php artisan schedule:work
Saída da Tarefa
O agendador Laravel fornece vários métodos convenientes para trabalhar com a saída gerada pelas tarefas agendadas. Primeiro, usando o método sendOutputTo
, você pode enviar o output para um arquivo para inspeção posterior:
$schedule->command('emails:send') ->daily() ->sendOutputTo($filePath);
Se você quiser anexar o output a um determinado arquivo, você pode usar o método appendOutputTo
:
$schedule->command('emails:send') ->daily() ->appendOutputTo($filePath);
Usando o método emailOutputTo
, você pode enviar o output por e-mail para um endereço de e-mail de sua escolha. Antes de enviar o output de uma tarefa por e-mail, você deve configurar os serviços de e-mail do Laravel:
$schedule->command('report:generate') ->daily() ->sendOutputTo($filePath) ->emailOutputTo('');
Se você só quiser enviar o output por e-mail se o comando programado do Artisan ou do sistema terminar com um código de saída diferente de zero, use o método emailOutputOnFailure
:
$schedule->command('report:generate') ->daily() ->emailOutputOnFailure('');
{notinha}. Os métodos
emailOutputTo
,emailOutputOnFailure
,sendOutputTo
, eappendOutputTo
são exclusivos dos métodoscommand
eexec
.Os métodos
Gancho de Tarefas
Usando os métodos before
e after
, você pode especificar o código a ser executado antes e depois da tarefa agendada:
$schedule->command('emails:send') ->daily() ->before(function () { // The task is about to execute... }) ->after(function () { // The task has executed... });
Os métodos onSuccess
e onFailure
permitem especificar o código a ser executado se a tarefa agendada for bem sucedida ou falhar. Uma falha indica que o comando programado Artisan ou sistema terminou com um código de saída diferente de zero:
$schedule->command('emails:send') ->daily() ->onSuccess(function () { // The task succeeded... }) ->onFailure(function () { // The task failed... });
Se a saída estiver disponível a partir do seu comando, você pode acessá-la no seu after
, onSuccess
ou onFailure
ganchos, digitando uma instância de Illuminate\Support\Stringable
como o argumento $output
da definição de fechamento do seu gancho:
use Illuminate\Support\Stringable;$schedule->command('emails:send') ->daily() ->onSuccess(function (Stringable $output) { // The task succeeded... }) ->onFailure(function (Stringable $output) { // The task failed... });
Pingando URLs
Usando os métodos pingBefore
e thenPing
, o agendador pode automaticamente pingar uma determinada URL antes ou depois da execução de uma tarefa. Este método é útil para notificar um serviço externo, como o Enviador, que sua tarefa agendada está começando ou terminou a execução:
$schedule->command('emails:send') ->daily() ->pingBefore($url) ->thenPing($url);
Os métodos pingBeforeIf
e thenPingIf
podem ser usados para pingar uma determinada URL somente se uma determinada condição for true
:
$schedule->command('emails:send') ->daily() ->pingBeforeIf($condition, $url) ->thenPingIf($condition, $url);
Os métodos pingOnSuccess
e pingOnFailure
podem ser usados para pingar uma determinada URL somente se a tarefa tiver sucesso ou falhar. Uma falha indica que o comando programado Artisan ou sistema terminou com um código de saída não zero:
$schedule->command('emails:send') ->daily() ->pingOnSuccess($successUrl) ->pingOnFailure($failureUrl);
Todos os métodos ping requerem a biblioteca Guzzle HTTP. Guzzle é normalmente instalado em todos os novos projetos Laravel por padrão, mas você pode instalar manualmente o Guzzle em seu projeto usando o gerenciador de pacotes Composer se ele tiver sido removido acidentalmente:
composer require guzzlehttp/guzzle
Deixe uma resposta