If you're asking "What is Yii?" check out my previous tutorial: Introduction to the Yii Framework, which reviews the benefits of Yii and provides an overview of the 2014-10 New features of Yii 2.0 released in March. Well>
In this Programming with Yii2 series, I will guide readers in using the Yii2 PHP framework. In today’s tutorial, I’ll share with you how to leverage Yii’s console functionality to run cron jobs.
In the past, I used wget — a web-accessible URL — in a cron job to run my background tasks. This raises security concerns and has some performance issues. While I discussed some ways to mitigate risks in our Boot Series security feature, I had hoped to transition to console-driven commands. With Yii2 this is fairly simple.
For today's example, I'll be demonstrating the console-based cron command on my Twixxr site, which I describe in this Twitter API episode. Due to rate limiting and performance management issues, the Twitter API relies heavily on efficient, reliable cron jobs. So this is a great example to share with you.
Before I begin, I want to reiterate: I always appreciate your ideas and feedback. If you have questions or topic suggestions, please post your thoughts in the comments below. You can also contact me directly on Twitter @reifman.
Wikipedia describes cron as "a time-based job scheduler in Unix-like computer operating systems." This is quite accurate. Basically, cron runs all the background tasks we need to run web services, from log management and backups to API requests to database cleanup.
To view existing cron jobs on the server, you would typically enter sudo crontab -l
and see something like this:
# Edit this file to introduce tasks to be run by cron. # # Each task to run has to be defined through a single line # indicating with different fields when the task will be run # and what command to run for the task # # To define the time you can provide concrete values for # minute (m), hour (h), day of month (dom), month (mon), # and day of week (dow) or use '*' in these fields (for 'any').# # Notice that tasks will be started based on the cron's system # daemon's notion of time and timezones. # # Output of the crontab jobs (including errors) is sent through # email to the user the crontab file belongs to (unless redirected). # # For example, you can run a backup of all your user accounts # at 5 a.m every week with: # 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/ # # For more information see the manual pages of crontab(5) and cron(8) # # m h dom mon dow command */3 * * * * wget -O /dev/null https://meetingplanner.io/daemon/frequent */15 * * * * wget -O /dev/null http://meetingplanner.io/daemon/quarter 0 * * * * wget -O /dev/null http://meetingplanner.io/daemon/hourly 15 1 * * * wget -O /dev/null http://meetingplanner.io/daemon/overnight 40 2 * * * /usr/sbin/automysqlbackup 15 3 * * 5 wget -O /dev/null http://meetingplanner.io/daemon/weekly 30 2 * * 1 /opt/letsencrypt/letsencrypt-auto renew >> /var/log/le-renew.log
The left side specifies to activate these tasks every 3 or 15 minutes or every day at midnight, etc., and the right side is the script to run. See alsoUsing Cron Jobs to Schedule Tasks (Envato Tuts).
Please note that the Let's Encrypt script is a unique console command. It is run from the command line on our server. However, all of my meeting schedule tasks above are run via wget. It's like a bot running requests on the web browser at a specific time against our web application that performs background tasks.
In addition to the overhead required for external web requests and timeout constraints for scripts on the server, you must also secure these access points. Here's an example of how meeting planners can do this:
// only cron jobs and admins can run this controller's actions public function beforeAction($action) { // your custom code here, if you want the code to run before action filters, // which are triggered on the [[EVENT_BEFORE_ACTION]] event, e.g. PageCache or AccessControl if (!parent::beforeAction($action)) { return false; } // other custom code here if (( $_SERVER['REMOTE_ADDR'] == $_SERVER['SERVER_ADDR'] ) || (!\Yii::$app->user->isGuest && \common\models\User::findOne(Yii::$app->user->getId())->isAdmin())) { return true; } return false; // or false to not run the action }
It verifies that the user is logged in as an administrator or is running locally on the server with the same Internet IP address.
Alex Makarov is one of the main volunteers in the development of the Yii framework and he helps answer my questions when I write regularly about the Envato Tuts framework. After reading my security incident, he asked me why I didn't use Yii2's native console functionality to execute cron jobs. Basically I don't know.
Just like I had a /frontend/controllers/DaemonController.php, I created a /console/controllers/DaemonController.php. In this tutorial, I'll do this for a smaller, simpler Twixxr web service.
I'm used to using the console to run database migrations (e.g. ./yii migrate/up 7
), but that's about it. I'd love to try using it to perform background tasks.
As I wrote in a previous tutorial, my nascent website Twixxr required a large number of background processes to regularly rotate API calls to satisfy all user requests to socialize with female-owned influencer Twitter accounts.
The homepage is as follows:
So I thought Twixxr would be a good testing platform for running console based cron controllers.
This is the core of my new console-based DaemonController.php:
<?php namespace console\controllers; use Yii; use yii\helpers\Url; use yii\console\Controller; use frontend\models\Twixxr; /** * Test controller */ class DaemonController extends Controller { public function actionIndex() { echo "Yes, cron service is running."; } public function actionFrequent() { // called every two minutes // */2 * * * * ~/sites/www/yii2/yii test $time_start = microtime(true); $x = new \frontend\models\Twixxr(); $x->process($time_start); $time_end = microtime(true); echo 'Processing for '.($time_end-$time_start).' seconds'; } public function actionQuarter() { // called every fifteen minutes $x = new \frontend\models\Twixxr(); $x->loadProfiles(); } public function actionHourly() { // every hour $current_hour = date('G'); if ($current_hour%4) { // every four hours } if ($current_hour%6) { // every six hours } }
Please note that it is very similar in structure to my front-end based controller, but it is not securely accessible over the network because it is located in the /console tree. The Apache web server site is not configured to browse this zone.
So, in the example above, actionFrequent()
will be called every two to three minutes. It handles another set of Twixxr friendship requests. actionQuarter()
on the other hand is called every 15 minutes and updates the browsing account's profile information. Let's see how scheduling works in a cron file.
Essentially, in my crontab file, I replaced wget with a direct Linux script as shown above for Let's Encrypt renewal.
You enter sudo crontab -e
to edit, or -l
to list its contents. Here is my Twixxr cron file:
$ sudo crontab -l # m h dom mon dow command */3 * * * * /var/www/twixxr/yii daemon/frequent */15 * * * * /var/www/twixxr/yii daemon/quarter 0 * * * * /var/www/twixxr/yii daemon/hourly 15 1 * * * /var/www/twixxr/yii daemon/overnight 15 3 * * 5 /var/www/twixxr/yii daemon/weekly #40 2 * * * /usr/sbin/automysqlbackup 30 2 * * 1 /usr/bin/letsencrypt renew >> /var/log/le-renew.log
这非常简单。 /var/www/twixxr/yii daemon/frequent
的左侧是 yii 解释器所在的路径,右侧是控制台控制器和调用的方法。 p>
切换时一切都很顺利。我还没有切换 Meeting Planner,因为我想做更多测试。当后台任务中断时,很难知道也很难调试它们(尽管 Sentry 错误日志记录有很大帮助)。
我遇到的一个问题是控制台命名空间与前端命名空间不同,因此,例如,我在教程中设置的 SiteHelper.php 组件(该组件描述了从单个代码库运行多个网站)失败了当我调用它时。删除它是有效的,但我需要运行测试以确保底层后台代码仍然有效。不过,大部分情况下切换都很顺利。
与任何其他代码更改一样,彻底测试和监控。
展望未来,我将探索在 Yii2 框架内构建 REST API,该框架恰好依赖于创建一个不同的子树,例如控制台树,但用于外部 API。当然,这会带来复杂的身份验证和安全问题……所以与您一起探索这些将会很有趣。我将从多个角度研究 API。我对此感到非常兴奋。
请观看我的“使用 Yii2 编程”系列中即将推出的教程,我将继续深入研究该框架的不同方面。另请浏览“使用 PHP 构建您的初创公司”系列,其中记录了构建 Simple Planner 和 Meeting Planner 的过程。
如果您想知道下一个 Yii2 教程何时发布,请在 Twitter 上关注我 @reifman 或查看我的讲师页面以获取更新。
The above is the detailed content of Yii2 Programming Guide: How to run Cron service. For more information, please follow other related articles on the PHP Chinese website!