【备忘】php命令行异步执行超长时间任务
环境说明:
操作系统:windows10
IDE:phpstorm
开发语言:php7.4
框架:thinkphp5.1
测试环境:linux+windows均测试通过。
初级方法:
function longRunningTask()
{$root_path = Tools::get_root_path();$scriptPath = $root_path . 'public/LongTaskRunner.php';// 定义命令行指令,并以后台方式运行(Linux)$command = 'php ' . escapeshellarg($scriptPath) . ' > /dev/null 2>&1 &';// 使用 exec 执行命令并立即返回$output = [];$returnCode = 0;exec($command, $output, $returnCode);//执行结果Tools::log_to_write_txt([$root_path . 'runtime/log/exec_debug.log', "Command: $command\nReturn Code: $returnCode\nOutput: " . print_r($output, true)]);return json(Tools::set_ok('任务已启动,正在后台运行。'));
}
然后在目标文件夹新建LongTaskRunner.php文件即可。
这是原始方法,只能执行脚本文件。
如果要执行类则需要以下高阶方法。
进阶方法:
使用自定义命令。
步骤:
- 编写自定义命令类
- 到command.php类中注册
- 控制台测试
自定义命令类示例:
<?phpnamespace app\command;use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\console\input\Argument;
use think\console\input\Option;class TestCommand extends Command
{/*** desc:这个方法用于定义命令的基本结构,包括名称、参数、选项以及描述。**/protected function configure(){//命令名$this->setName('hello')//位置参数,OPTIONAL可选 写法如:php think hello 1(类似name=1)->addArgument('name', Argument::OPTIONAL, "your name")//参数选项名,使用时使用--符号,VALUE_REQUIRED必填,//选项支持更灵活的命名方式://短格式:一个字母,如 -c//命名参数,写法如:php think hello --file_id=1(写明了参数名和值,参数名file_id不可省略)//长格式:多个单词,用短横线或下划线分隔,如 --city-name 或 --city_name->addOption('city', null, Option::VALUE_REQUIRED, 'city name')->setDescription('Say Hello');}/*** desc:这是命令的核心逻辑部分,当运行 hello 命令时,此方法会被调用。*/protected function execute(Input $input, Output $output){$name = trim($input->getArgument('name'));$name = $name ?: 'hello world';//判断用户是否提供了 --city 选项。如果有,做什么;如果没有,做什么。if ($input->hasOption('city')) {$city = PHP_EOL . 'From ' . $input->getOption('city');} else {$city = '';}//向终端输出$output->writeln("Hello," . $name . '!' . $city);}
}
说明:
这是一个自定义命令类,继承了think\console\Command类。
名称空间:目录自定义,命名空间跟随目录即可。
在configure方法中编写命令。
在execute方法中编写命令要执行的业务逻辑。
$this->writeln()方法是向控制台输出信息。
日志可以自己另外加上。
END