当前位置: 首页 > 后端技术 > PHP

Laravel计划任务剖析——创建和运行系统命令

时间:2023-03-30 02:49:59 PHP

翻译GitHubhttps://github.com/yuansir/diving-laravel-zh原文链接https://divinglaravel.com/task-scheduling/building-and-running-the-os-command当触发计划事件时,Laravel的计划管理器会在代表该事件的Illuminate\Console\Scheduling\Event对象上调用run()方法,这发生在Illuminate\Console\Scheduling\ScheduleRunCommand中。当计划任务的事件启动时,Laravel的计划管理器会调用Illuminate\Console\Scheduling\Event对象的run()方法,表明该事件发生在Illuminate\Console\Scheduling\ScheduleRunCommand中。这个run()方法构建命令语法并使用SymfonyProcess组件在操作系统上运行它,但是在构建命令之前它首先检查命令是否应该在后台运行,默认情况下所有命令都在前台运行,除非你在调度命令时使用以下方法:run()方法构建命令语法并使用SymfonyProcess组件在操作系统上运行它,但在构建命令之前,它首先检查命令是否应该在后台运行,默认情况下,所有命令都在前台运行,除非您使用以下方式安排命令:->runInBackground()我什么时候需要在后台运行命令?想象一下,如果你有几个任务应该同时运行,比如每小时运行一次,使用默认设置Laravel将指示操作系统一个接一个地运行命令:运行命令:~phpartisanupdate:coupons#等待命令tofinish#...#commandfinished,nowwerunthenext~phpartisansend:mail但是,你可以指示操作系统在后台运行命令,这样你就可以n继续推送更多命令,即使其他命令尚未完成:但是,您可以指示操作系统在后台运行命令,这样即使其他命令尚未完成,您也可以继续推送更多命令:~phpartisanupdate:coupons&~phpartisansend:mail&在命令末尾使用ampersand可以让您继续推送命令,而无需等待初始命令完成。run()方法检查runInBackground属性的值并决定接下来调用哪个方法,runCommandInForeground()或runCommandInBackground()。如果命令在前台运行,剩下的很简单:$this->callBeforeCallbacks($container);(newProcess($this->buildCommand(),base_path(),null,null,null))->run();$this->callAfterCallbacks($container);Laravel执行任何before-callbacks,将命令发送到OS,最后执行任何after-callbacks。Laravel执行任意的before-callbacks,向OS发送命令,最后执行任意的before-callbacks。然而,如果命令是在后台运行,Laravel调用callBeforeCallbacks(),发送命令,但不调用after-callbacks,原因如你所想,因为命令将在后台执行,所以如果我们此时调用callAfterCallbacks()它不会在命令完成后运行,一旦命令发送到操作系统就会运行。但是,如果命令在后台运行,Laravel会调用callBeforeCallbacks(),发送命令,但不会调用after-callbacks,原因如你所想,因为命令会在后台执行如果我们调用callAfterCallbacks()这时,那么命令完成后,它不会运行,一旦命令发送到操作系统,它就会运行。那么我们在后台运行命令时不会执行后回调吗?那么我们在后台运行命令时不会执行后回调吗?他们运行,laravel使用另一个在原始命令完成后运行的命令来执行此操作:(phpartisanupdate:coupons;phpartisanschedule:finisheventMutex)&此命令将导致一系列两个命令依次运行但在后台运行,因此,在您的update:coupons命令完成后,schedule:finish命令将在给定当前事件的Mutex的情况下运行,Laravel使用此ID定位事件并运行其后回调。此命令导致一系列两个命令一个接一个地运行,但在后台运行,因此在您的update:coupons命令完成schedule:finish命令后,给定当前事件的Mutex运行,使用此IDLaravel查找事件并运行其回调。构建命令字符串当调度程序调用runCommandInForeground()或runCommandInBackground()方法时,将调用buildCommand()来构建操作系统将运行的实际命令,此方法仅执行以下操作:runCommandInForeground()或runCommandInBackground()方法,调用buildCommand()来构建操作系统将运行的实际命令,此方法仅执行以下操作:return(newCommandBuilder)->buildCommand($this);要构建命令,需要了解以下配置:命令mutex输出应发送到的位置确定是否应将输出附加到运行命令的用户BackgroundvsForeground输出应该附加到运行命令的用户的背景还是前景?命令互斥锁互斥锁是为每个命令设置的唯一ID,Laravel使用它主要是为了防止我们稍后讨论的命令重叠,但它也将它用作命令的唯一ID。互斥量是每个命令的唯一ID的集合,Laravel主要使用它来防止命令重叠,我们将在后面讨论,但它也将它用作命令的唯一ID。Laravel在Event::mutexName()方法中定义每个命令的互斥量:Laravel在Event::mutexName()方法中定义每个命令的互斥量:return'framework'.DIRECTORY_SEPARATOR.'schedule-'.sha1($this->expression.$this->command);所以它是事件的CRON表达式和命令字符串的组合。所以它是事件的CRON表达式和命令字符串的组合。但是,对于回调事件,互斥量是按如下方式创建的:然而,对于回调事件,互斥量是这样创建的:return'framework/schedule-'.sha1($this->description);所以为了确保你的回调事件有一个正确的互斥锁,你需要为命令设置一个描述:所以为了确保你的回调事件有一个正确的互斥锁,你需要为命令设置一个描述:$schedule->call(function(){DB::table('recent_users')->delete();})->daily()->description('清除最近用户');处理输出控制输出默认情况下,命令的输出被发送到/dev/null这是一个丢弃写入它的数据的特殊文件,但是如果你想将命令输出发送到某个地方,你可以使用sendOutputTo()方法更改它,同时定义命令:默认情况下,命令的输出被发送到/dev/null,这是一个写入丢弃数据的特殊文件,但是如果你想把命令输出发送到某个地方,你可以用sendOutputTo():$schedule->command('mail:send')->sendOutputTo('/home/scheduler.log');但这将导致输出覆盖每次写入scheduler.log文件的内容,以附加输出inst你可以使用appendOutputTo()。下面是该命令的样子:但这将导致输出覆盖每次写入scheduler.log文件的内容,如果附加了输出,您可以使用appendOutputTo()命令,如下所示://将输出附加到filephpartisanmail:send>>/home/scheduler.log2>&1//Overwritefilephpartisanmail:send>/home/scheduler.log2>&12>&1指示操作系统将错误输出重定向到标准输出通道,简而言之表示错误和输出的单词将记录到您的文件中。2>&1指示操作系统将错误输出重定向到标准输出通道,简而言之,这意味着错误和输出将被记录到您的文件中。使用正确的用户当您设置一个用户来运行命令时:$schedule->command('mail:send')->user('forge');Laravel会运行命令如下:sudo-uforge--sh-c'phpartisanmail:send>>/home/scheduler.log2>&1'后台允许运行正如我们之前讨论的,如果需要在后台运行,命令字符串将如下所示:如前所述,如果需要在后台运行,命令字符串将如下所示:如前所述,命令字符串看起来像这样,它在后台运行:(phpartisanupdate:coupons;phpartisanschedule:finisheventMutex)&But这只是一个简短的形式,这里是实际运行的完整字符串:但这只是一个简短的形式,这是实际有效的完整字符串:(phpartisanupdate:coupons>>/home/scheduler.log2>&1;phpartisanschedule:finisheventMutex)>/dev/null2>&1&Orthisifyoudon't将其设置为追加输出&没有d定义自定义目标:或者如果您没有将其设置为追加输出并且没有定义自定义输出位置:(phpartisanupdate:coupons>/dev/null2>&1;phpartisanschedule:finisheventMutex)>/dev/null2>&1&Sendtheoutputviaemail您可以选择使用emailOutputTo()方法将命令输出发送到电子邮件地址:您可以通过调用emailOutputTo()方法将命令输出发送到电子邮件$schedule->命令('邮件:发送')->emailOutputTo(['myemail@mail.com','myOtheremail@mail.com']);如果您只想在有输出的情况下接收电子邮件,您也可以使用emailWrittenOutputTo()代替,否则即使现在输出供您查看,您也会收到电子邮件,这只是命令运行的通知。如果有输出,您也可以使用emailWrittenOutputTo(),否则即使您现在看到了输出,您也会收到一封电子邮件,它只是运行通知的命令此方法将更新计划事件的输出属性并将其指向存储/日志目录中的文件:if(is_null($this->output)||$this->output==$this->getDefaultOutput()){$this->sendOutputTo(storage_path('logs/schedule-'.sha1($this->mutexName()).'.log'));}请注意,这仅在您尚未设置自定义输出目标。接下来Laravel将注册一个后回调,它将尝试定位该文件,读取其内容并将其发送给指定的收件人。接下来,Laravel将注册一个后回调,它会尝试定位该文件、读取其内容并将其发送给指定的收件人。它被发送到指定的收件人。$text=file_exists($this->output)?file_get_contents($this->output):'';if($onlyIfOutputExists&&empty($text)){return;}$mailer->raw($text,function($m)使用($addresses){$m->to($addresses)->subject($this->getEmailSubject());});转载请注明:如果您觉得本文对您很有帮助,不妨打赏一下本文链接地址:剖析Laravel定时任务--创建和运行系统命令