YII2定时任务 crontab环境变量问题

程序人生
最近使用了YII2的定时任务模块,在配置过程中踩了不少坑,在这给自己做个记录或给有此需要的朋友做个参考。

请注意,以下所有代码都是在Centos7环境下执行的,其它linux系统大同小异。

一、创建YII2的console定时任务

Yii2内置有强大的定时任务执行功能(Console),默认在项目根目录的console目录;也可根据需求在其它相关模块下创建。
以下相关代码示例是创建在根目录的console目录
我们先建一个TaskController.php的控制器
<?php
namespace console\controllers;
use yii\console\Controller;
  
class TaskController extends Controller
{
    public function actionIndex()
    {
    	file_put_contents('task.log', date('Y-m-d H:i:s') . "\n", FILE_APPEND);
        echo "我是index方法\n";
    }

    public function actionTest()
    {
        echo "我是test方法\n";
    }
}

二、命令行测试能否正常运行

在项目根目录定时任务脚本所有位置执行如下命令(说明:yii是linux脚本,yii.bat是windows脚本)
#切换到项目根目录
cd /var/www/PhpWorkspace/yii2mini
#运行console定时任务
php yii task/index
注意:如上的命令是在php已被加入环境变量的情况下,可以直接使用php,否则需要写完整的php绝对路径

如直接复制上面的代码来执行,不出意外的话,会报错
Unknown command: task/index

这是因为控制器的命名空间和配置文件项controllerNamespace值不一致造成的,修改配置项controllerNamespace为console\controllers

再运行,又报如下错误

这是因为目录别名的问题,在配置文件中定义目录别名

Yii::setAlias('@console', (dirname(__DIR__)) . '/console');

然后再运行

$ php yii task/index
我是index方法

此时在项目根目录下有task.log文件生成并写入了当前时间,可根据写入的时间来判断是否成功执行。

三、创建定时任务

在centos7上可以利用 crontab 来执行计划任务,依赖于 crond 的系统服务,这个服务是系统自带的。
注:网上有人说第一次使用 crontab 需要安装crond服务;可以通过命令 rpm -qa|grep cron 查看是否安装了该服务。

#查看状态
systemctl status crond
#设为开机启动
systemctl enable crond
#启动crond服务
systemctl start crond
配置定时任务流程如下:
#打开定时任务编辑界面
crontab -e
#写入定时程序代码
*/1 * * * * php /var/www/PhpWorkspace/yii2mini/yii task/index
#保存退出
:wq
#有如下提示,说明定时任务创建成功
crontab: installing new crontab
#重启crontab使任务生效
systemctl restart crond

上面的例子是表示每一分钟执行一次任务(本文末有定时任务设置基本介绍)

OK,静静的等待一分钟,发现任务并未执行
后经排查是因为crontab的环境变量和root用户的环境变量不同导致的
这是crontab的环境变量

执行env命令得到当前用户的环境变量

将PATH环境变量添加到crontab第一行,然后保存退出,重启crond任务(亦可直接修改/etc/crontab的默认环境变量)

好吧,又静静的等待了一分钟,你如果发现任务依旧未执行,请尝试修改定时任务脚本为:

*/1 * * * * cd /var/www/PhpWorkspace/yii2mini/ && php yii task/index

我分析可能的原因是定时的脚本执行环境和执行的脚本代码所在的目录不一样造成的。
现在你会发现任务已成功执行,每隔一分钟会在task.log中写入一个时间


◆ 定时任务设置的一些基本介绍
基本格式 :
*  *  *  *  *  command
分 时 日 月 周 命令

第1列表示分钟1~59 每分钟用*或者 */1表示
第2列表示小时1~23(0表示0点)
第3列表示日期1~31
第4列表示月份1~12
第5列标识号星期0~6(0表示星期天)
第6列要运行的命令


*         

正在加载验证码......