- Introducción
- Definición de programaciones
- Programación de comandos Artisan
- Programación de trabajos en cola
- Programación de comandos Shell
- Opciones de frecuencia de programación
- Zonas horarias
- Prevención de solapamientos de tareas
- Ejecución de tareas en un servidor
- Tareas en segundo plano
- Modo de mantenimiento
.
- Ejecución del programador
- Ejecución local del programador
- Salida de tareas
- Ganchos de tareas
- Introducción
- Definiendo Horarios
- Programación de comandos Artisan
- Programación de trabajos en cola
- Programación de comandos Shell
- Opciones de frecuencia de programación
- Limitaciones de días
- Restricciones de Hora
- Constricciones de prueba de verdad
- Restricciones de entorno
- Zonas horarias
- Prevención de solapamientos de tareas
- Ejecución de tareas en un servidor
- Tareas de fondo
- Modo de mantenimiento
- Ejecución del programador
- Ejecutando el planificador localmente
- Salida de la tarea
- Hooks de tareas
- Ping URLs
Introducción
En el pasado, es posible que haya escrito una entrada de configuración de cron para cada tarea que necesitaba programar en su servidor. Sin embargo, esto puede convertirse rápidamente en un dolor porque su programación de tareas ya no está en el control de origen y debe SSH en su servidor para ver sus entradas cron existentes o añadir entradas adicionales.
El planificador de comandos de Laravel ofrece un nuevo enfoque para la gestión de las tareas programadas en su servidor. El programador le permite definir de forma fluida y expresiva su programación de comandos dentro de su propia aplicación Laravel. Cuando se utiliza el planificador, sólo se necesita una única entrada cron en su servidor. Su programación de tareas se define en el método app/Console/Kernel.php
del archivo schedule
. Para ayudarle a empezar, un ejemplo simple se define dentro del método.
Definiendo Horarios
Usted puede definir todas sus tareas programadas en el método schedule
de la clase App\Console\Kernel
de su aplicación. Para empezar, veamos un ejemplo. En este ejemplo, programaremos un cierre para que sea llamado cada día a medianoche. Dentro del cierre ejecutaremos una consulta a la base de datos para limpiar una tabla:
<?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(); }}
Además de programar usando cierres, también puedes programar objetos invocables. Los objetos invocables son simples clases de PHP que contienen un método __invoke
:
$schedule->call(new DeleteRecentUsers)->daily();
Si desea ver una visión general de sus tareas programadas y la próxima vez que están programadas para ejecutarse, puede utilizar el comando schedule:list
Artisan:
php artisan schedule:list
Programación de comandos Artisan
Además de programar cierres, también puede programar comandos Artisan y comandos del sistema. Por ejemplo, puede utilizar el método command
para programar un comando de Artisan utilizando el nombre o la clase del comando.
Cuando se programan comandos de Artisan utilizando el nombre de la clase del comando, puede pasar una matriz de argumentos de línea de comandos adicionales que deben proporcionarse al comando cuando se invoca:
use App\Console\Commands\SendEmailsCommand;$schedule->command('emails:send Taylor --force')->daily();$schedule->command(SendEmailsCommand::class, )->daily();
Programación de trabajos en cola
El método job
puede utilizarse para programar un trabajo en cola. Este método proporciona una manera conveniente de programar trabajos en cola sin utilizar el método call
para definir los cierres para poner en cola el trabajo:
use App\Jobs\Heartbeat;$schedule->job(new Heartbeat)->everyFiveMinutes();
Se puede proporcionar un segundo y tercer argumento opcional al método job
que especifica el nombre de la cola y la conexión de la cola que se debe utilizar para poner en cola el trabajo:
use App\Jobs\Heartbeat;// Dispatch the job to the "heartbeats" queue on the "sqs" connection...$schedule->job(new Heartbeat, 'heartbeats', 'sqs')->everyFiveMinutes();
Programación de comandos Shell
El método exec
puede utilizarse para emitir un comando al sistema operativo:
$schedule->exec('node /home/forge/script.js')->daily();
Opciones de frecuencia de programación
Ya hemos visto algunos ejemplos de cómo se puede configurar una tarea para que se ejecute a intervalos específicos. Sin embargo, hay muchas más frecuencias de programación de tareas que puede asignar a una tarea:
Método | Descripción |
---|---|
->cron('* * * * *'); |
|
->everyMinute(); |
Ejecutar la tarea cada minuto |
->everyTwoMinutes(); |
Ejecutar la tarea cada dos minutos |
->everyThreeMinutes(); |
Ejecutar la tarea cada tres minutos |
->everyFourMinutes(); |
Ejecutar la tarea cada cuatro minutos |
->everyFiveMinutes(); |
Ejecutar la tarea cada cinco minutos |
->everyTenMinutes(); |
|
->everyFifteenMinutes(); |
|
->everyThirtyMinutes(); |
Ejecutar la tarea cada treinta minutos |
->hourly(); |
Ejecutar la tarea cada hora |
->hourlyAt(17); |
Ejecutar la tarea cada hora a las 17 horas |
->everyTwoHours(); |
Ejecutar la tarea cada dos horas |
->everyThreeHours(); |
Ejecutar la tarea cada tres horas |
->everyFourHours(); |
Ejecutar la tarea cada cuatro horas |
->everySixHours(); |
Ejecutar la tarea cada seis horas |
->daily(); |
|
->dailyAt('13:00'); |
|
->twiceDaily(1, 13); |
Ejecutar la tarea todos los días a la 1:00 & 13:00 |
->weekly(); |
Ejecutar la tarea todos los domingos a las 00:00 |
->weeklyOn(1, '8:00'); |
|
->monthly(); |
|
->monthlyOn(4, '15:00'); |
Ejecutar la tarea cada mes el día 4 a las 15:00 |
->twiceMonthly(1, 16, '13:00'); |
Ejecutar la tarea mensualmente los días 1 y 16 a las 13:00 |
->lastDayOfMonth('15:00'); |
|
->quarterly(); |
Ejecutar la tarea el primer día de cada trimestre a las 00:00 |
->yearly(); |
|
->yearlyOn(6, 1, '17:00'); |
Ejecutar la tarea cada año el 1 de junio a las 17:00 |
->timezone('America/New_York'); |
Establezca la zona horaria para la tarea |
Estos métodos pueden combinarse con restricciones adicionales para crear programaciones aún más precisas que sólo se ejecuten en determinados días de la semana. Por ejemplo, puede programar un comando para que se ejecute semanalmente el lunes:
// 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');
A continuación se incluye una lista de restricciones de programación adicionales:
Método | Descripción |
---|---|
->weekdays(); |
|
->weekends(); |
Limitar la tarea a los fines de semana |
->sundays(); |
Limitar la tarea a los domingos |
->mondays(); |
Limitar la tarea al lunes |
->tuesdays(); |
Limitar la tarea al martes |
->wednesdays(); |
Limitar la tarea al miércoles |
->thursdays(); |
Limitar la tarea al jueves |
->fridays(); |
Limitar la tarea al viernes |
->saturdays(); |
Limitar la tarea al sábado |
->days(array|mixed); |
Limitar la tarea a días específicos |
->between($startTime, $endTime); |
Limitar la tarea para que se ejecute entre las horas de inicio y fin |
->unlessBetween($startTime, $endTime); |
Limitar la tarea para que no se ejecute entre las horas de inicio y final |
->when(Closure); |
Limitar la tarea basándose en una prueba de verdad |
->environments($env); |
Limitar la tarea a determinados entornos |
Limitaciones de días
El método days
puede utilizarse para limitar la ejecución de una tarea a días específicos de la semana. Por ejemplo, puede programar un comando para que se ejecute cada hora los domingos y los miércoles:
$schedule->command('emails:send') ->hourly() ->days();
Alternativamente, puede utilizar las constantes disponibles en la clase Illuminate\Console\Scheduling\Schedule
al definir los días en los que una tarea debe ejecutarse:
use Illuminate\Console\Scheduling\Schedule;$schedule->command('emails:send') ->hourly() ->days();
Restricciones de Hora
El método between
puede utilizarse para limitar la ejecución de una tarea basada en la hora del día:
$schedule->command('emails:send') ->hourly() ->between('7:00', '22:00');
De forma similar, el método unlessBetween
puede utilizarse para excluir la ejecución de una tarea durante un periodo de tiempo:
$schedule->command('emails:send') ->hourly() ->unlessBetween('23:00', '4:00');
Constricciones de prueba de verdad
El método when
puede utilizarse para limitar la ejecución de una tarea basándose en el resultado de una prueba de verdad dada. En otras palabras, si el cierre dado devuelve true
, la tarea se ejecutará siempre y cuando no haya otras condiciones de restricción que impidan la ejecución de la tarea:
$schedule->command('emails:send')->daily()->when(function () { return true;});
El método skip
puede verse como el inverso de when
. Si el método skip
devuelve true
, la tarea programada no se ejecutará:
$schedule->command('emails:send')->daily()->skip(function () { return true;});
Cuando se utilizan métodos when
encadenados, la orden programada sólo se ejecutará si todas las condiciones when
devuelven true
.
Restricciones de entorno
El método environments
puede utilizarse para ejecutar tareas sólo en los entornos dados (como se define por la variable de entorno APP_ENV
):
$schedule->command('emails:send') ->daily() ->environments();
Zonas horarias
Usando el método timezone
, puede especificar que la hora de una tarea programada debe ser interpretada dentro de una zona horaria determinada:
$schedule->command('report:generate') ->timezone('America/New_York') ->at('2:00')
Si está asignando repetidamente la misma zona horaria a todas sus tareas programadas, es posible que desee definir un método scheduleTimezone
en su clase App\Console\Kernel
. Este método debe devolver la zona horaria por defecto que se debe asignar a todas las tareas programadas:
/** * Get the timezone that should be used by default for scheduled events. * * @return \DateTimeZone|string|null */protected function scheduleTimezone(){ return 'America/Chicago';}
{nota} Recuerde que algunas zonas horarias utilizan el horario de verano. Cuando se produce el cambio de horario de verano, la tarea programada puede ejecutarse dos veces o incluso no ejecutarse. Por esta razón, recomendamos evitar la programación de zonas horarias cuando sea posible.
Prevención de solapamientos de tareas
Por defecto, las tareas programadas se ejecutarán incluso si la instancia anterior de la tarea sigue en marcha. Para evitarlo, puede utilizar el método withoutOverlapping
:
$schedule->command('emails:send')->withoutOverlapping();
En este ejemplo, el comando emails:send
Artisan se ejecutará cada minuto si no está ya en marcha. El método withoutOverlapping
es especialmente útil si tiene tareas que varían drásticamente en su tiempo de ejecución, lo que le impide predecir exactamente cuánto tiempo tomará una tarea determinada.
Si es necesario, puede especificar cuántos minutos deben pasar antes de que expire el bloqueo «sin superposición». Por defecto, el bloqueo expirará después de 24 horas:
$schedule->command('emails:send')->withoutOverlapping(10);
Ejecución de tareas en un servidor
{nota} Para utilizar esta función, su aplicación debe utilizar el controlador de caché
database
,memcached
,dynamodb
oredis
como controlador de caché predeterminado de su aplicación. Además, todos los servidores deben comunicarse con el mismo servidor de caché central.
Si el programador de su aplicación se ejecuta en varios servidores, puede limitar un trabajo programado para que sólo se ejecute en un único servidor. Por ejemplo, suponga que tiene una tarea programada que genera un nuevo informe cada viernes por la noche. Si el programador de tareas se ejecuta en tres servidores de trabajadores, la tarea programada se ejecutará en los tres servidores y generará el informe tres veces. Para indicar que la tarea debe ejecutarse sólo en un servidor, utilice el método onOneServer
al definir la tarea programada. El primer servidor que obtenga la tarea asegurará un bloqueo atómico en el trabajo para evitar que otros servidores ejecuten la misma tarea al mismo tiempo:
$schedule->command('report:generate') ->fridays() ->at('17:00') ->onOneServer();
Tareas de fondo
Por defecto, varias tareas programadas al mismo tiempo se ejecutarán secuencialmente según el orden en que se definan en su método schedule
. Si tiene tareas de larga duración, esto puede hacer que las tareas posteriores se inicien mucho más tarde de lo previsto. Si desea ejecutar tareas en segundo plano para que todas se ejecuten simultáneamente, puede utilizar el método runInBackground
:
$schedule->command('analytics:report') ->daily() ->runInBackground();
{nota} El método
runInBackground
sólo puede utilizarse cuando se programan tareas a través de los métodoscommand
yexec
.
Modo de mantenimiento
Las tareas programadas de su aplicación no se ejecutarán cuando la aplicación esté en modo de mantenimiento, ya que no queremos que sus tareas interfieran con cualquier mantenimiento inacabado que pueda estar realizando en su servidor. Sin embargo, si desea forzar la ejecución de una tarea incluso en modo de mantenimiento, puede llamar al método evenInMaintenanceMode
al definir la tarea:
$schedule->command('emails:send')->evenInMaintenanceMode();
Ejecución del programador
Ahora que hemos aprendido a definir las tareas programadas, vamos a discutir cómo ejecutarlas realmente en nuestro servidor. El comando schedule:run
Artisan evaluará todas tus tareas programadas y determinará si necesitan ejecutarse basándose en la hora actual del servidor.
Así que, al usar el programador de Laravel, sólo necesitamos añadir una única entrada de configuración cron a nuestro servidor que ejecute el comando schedule:run
cada minuto. Si no sabes cómo añadir entradas cron a tu servidor, considera usar un servicio como Laravel Forge que puede gestionar las entradas cron por ti:
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
Ejecutando el planificador localmente
Típicamente, no añadirías una entrada cron del planificador a tu máquina de desarrollo local. En su lugar, puede utilizar el comando schedule:work
Artisan. Este comando se ejecutará en primer plano e invocará el planificador cada minuto hasta que usted termine el comando:
php artisan schedule:work
Salida de la tarea
El planificador de Laravel proporciona varios métodos convenientes para trabajar con la salida generada por las tareas programadas. En primer lugar, utilizando el método sendOutputTo
, puede enviar la salida a un archivo para su posterior inspección:
$schedule->command('emails:send') ->daily() ->sendOutputTo($filePath);
Si desea añadir la salida a un archivo determinado, puede utilizar el método appendOutputTo
:
$schedule->command('emails:send') ->daily() ->appendOutputTo($filePath);
Usando el método emailOutputTo
, puede enviar la salida a una dirección de correo electrónico de su elección. Antes de enviar por correo electrónico la salida de una tarea, debe configurar los servicios de correo electrónico de Laravel:
$schedule->command('report:generate') ->daily() ->sendOutputTo($filePath) ->emailOutputTo('');
Si sólo desea enviar por correo electrónico la salida si el Artisan programado o el comando del sistema termina con un código de salida distinto de cero, utilice el método emailOutputOnFailure
:
$schedule->command('report:generate') ->daily() ->emailOutputOnFailure('');
{nota} Los métodos
emailOutputTo
,emailOutputOnFailure
,sendOutputTo
yappendOutputTo
son exclusivos de los métodoscommand
yexec
.
Hooks de tareas
Usando los métodos before
y after
, puede especificar el código que se ejecutará antes y después de que se ejecute la tarea programada:
$schedule->command('emails:send') ->daily() ->before(function () { // The task is about to execute... }) ->after(function () { // The task has executed... });
Los métodos onSuccess
y onFailure
permiten especificar el código que se ejecutará si la tarea programada tiene éxito o falla. Un fallo indica que el comando programado de Artisan o del sistema terminó con un código de salida distinto de cero:
$schedule->command('emails:send') ->daily() ->onSuccess(function () { // The task succeeded... }) ->onFailure(function () { // The task failed... });
Si la salida está disponible desde su comando, puede acceder a ella en sus ganchos after
, onSuccess
o onFailure
indicando una instancia Illuminate\Support\Stringable
como el argumento $output
de la definición de cierre de su gancho:
use Illuminate\Support\Stringable;$schedule->command('emails:send') ->daily() ->onSuccess(function (Stringable $output) { // The task succeeded... }) ->onFailure(function (Stringable $output) { // The task failed... });
Ping URLs
Usando los métodos pingBefore
y thenPing
, el programador puede hacer ping automáticamente a una URL dada antes o después de que se ejecute una tarea. Este método es útil para notificar a un servicio externo, como Envoyer, que su tarea programada está comenzando o ha terminado de ejecutarse:
$schedule->command('emails:send') ->daily() ->pingBefore($url) ->thenPing($url);
Los métodos pingBeforeIf
y thenPingIf
pueden utilizarse para hacer ping a una URL dada sólo si una condición dada es true
:
$schedule->command('emails:send') ->daily() ->pingBeforeIf($condition, $url) ->thenPingIf($condition, $url);
Los métodos pingOnSuccess
y pingOnFailure
pueden utilizarse para hacer ping a una URL dada sólo si la tarea tiene éxito o falla. Un fallo indica que el comando programado de Artisan o del sistema terminó con un código de salida distinto de cero:
$schedule->command('emails:send') ->daily() ->pingOnSuccess($successUrl) ->pingOnFailure($failureUrl);
Todos los métodos de ping requieren la biblioteca Guzzle HTTP. Guzzle se instala normalmente en todos los nuevos proyectos de Laravel por defecto, pero, puede instalar manualmente Guzzle en su proyecto utilizando el gestor de paquetes Composer si se ha eliminado accidentalmente:
composer require guzzlehttp/guzzle
Deja una respuesta