I have an application which is built in CakePHP 3.
It uses Console Commands to execute several intensive processes in the background using cron.
The application consists of 5 individual commands:
src/Command/Stage1Command.php
src/Command/Stage2Command.php
src/Command/Stage3Command.php
src/Command/Stage4Command.php
src/Command/Stage5Command.php
These can be executedmanuallyby running each one individually, e.g. to execute Stage1Command.php
:
$ php bin/cake.php stage1
To make them run via Cron, I created a 6th command ( src/Command/RunAllCommand.php
) which goes through these in order.
// src/Command/RunAllCommand.php
class RunAllCommand extends Command
{
public function execute(Arguments $args, ConsoleIo $io)
{
$stage1 = new Step1Command();
$this->executeCommand($stage1);
// ...
$stage5 = new Stage5Command();
$this->executeCommand($stage5);
}
}
This works fine so I can now execute everything with 1 command, php bin/cake.php run_all
, which will be added as a cron task to automate running the 5 processes.
The problem I'm having is that each of the 5 commands ( Stage1Command
... Stage5Command
) produces output which appears on standard output in the console.
I need to be able to write the output produced by each of the 5 commands individually
into dynamically named
files.
So I can't do something like this
$ php bin/cake.php run_all > output.log
Because
output.log
would containeverything
, i.e. the output from all 5 commands.output.log
isn't a dynamic filename, it has been entered manually on the command line (or as the output destination of the cron task).
I looked at Redirecting PHP output to a text file and tried the following.
Addedob_start();
toRunAllCommand.php
:
namespace App\Command;
ob_start();
class RunAllCommand extends Command { ... }
After executing the first task ( Stage1Command
) capturing ob_get_clean()
to a variable called $content
:
$stage1 = new Step1Command();
$this->executeCommand($stage1);
$content = ob_get_clean();
When I var_dump($content);
it comes out as an empty string:
string(0) ""
But the output is still produced on the command line when executing php bin/cake.php run_all
(RunAllCommand.php).
My plan for the dynamic filename was to generate it with PHP inside RunAllCommand.php
, e.g.
// $id is a dynamic ID generated from a database call.
// This $id is being generated inside a foreach() loop so is different on each iteration (hence the dynamic nature of the filename).
$id = 234343;
$filename_stage1 = 'logs/stage1_' . $id . '.txt'; // e.g. "logs/stage1_234343.txt"
Then write $content
to the above file, e.g.
file_put_contents($filename_stage1, $content);
So I have 2 problems:
- The output is being echoed to the console, and unavailable in
$content
. - Assuming (1) is fixed, how to "reset" the output buffering such that I can use
file_put_contents
with 5 different filenames to capture the output for the relevant stage.
2条答案
按热度按时间wbgh16ku1#
在每个命令文件上,您可以使用LogTrait,然后在任何命令之前输出文件输出内容,以区分记录的命令,或者设置具有不同范围的日志配置,以输出到不同的文件。输出到cli-debug.log文件的示例。
gkl3eglg2#
我有两个建议来解决你的问题。
选项1 -使用shell_exec
shell_exec返回输出的字符串,因此您可以直接将其写入日志文件。
选项2 -覆盖控制台输出流
或者,一个更像CakePHP风格的方法是调用命令时稍有不同。如果您查看executeCommand()的内容,它会做一些检查,然后调用
command->run($args, $io)
此外,如果您查看
ConsoleIo
的构造方式,我们可以覆盖输出方法,这样我们就可以使用文件来代替php://stdout
,如果您查看ConsoleOutput的代码,它只是使用普通的fopen
和fwrite
。