Laravel 框架外的 Artisan::call()
Posted
技术标签:
【中文标题】Laravel 框架外的 Artisan::call()【英文标题】:Artisan::call() outside the Laravel framework 【发布时间】:2016-08-31 21:37:15 【问题描述】:我想为 Laravel 5.2
创建一个 cron 作业我的共享主机(在 OVH 上)只允许我指向文件的完整路径,并且我无法使用 Laravel 文档中推荐的 Cron 条目,即:
* * * * * php /path/to/artisan schedule:run >> /dev/null 2>&1
因此,我必须在 Laravel 框架之外的 .php 文件中调用 Artisan 命令。
这是我的public/cron.php
文件到目前为止的样子:
<?php
require __DIR__.'/../bootstrap/autoload.php';
use Illuminate\Support\Facades\Artisan;
Artisan::call('refresh');
refresh
是我在应用内重新生成缩略图的命令。
通过我的浏览器访问cron.php时(在本地XAMPP上测试),出现如下错误:
Fatal error: Uncaught RuntimeException: A facade root has not been set. in
C:\xampp\htdocs\site\vendor\laravel\framework\src\Illuminate\Support\Facades\Facade.php:210
Stack trace:
#0 C:\xampp\htdocs\site\public\cron.php(7): Illuminate\Support\Facades\Facade::__callStatic('call', Array)
#1 main thrown in C:\xampp\htdocs\site\vendor\laravel\framework\src\Illuminate\Support\Facades\Facade.php on line 210
我也尝试过启动应用,但没有任何区别
$app = require_once __DIR__.'/../bootstrap/app.php';
$app->boot();
为了避免使用 Artisan Facade,我尝试直接调用底层内核类:
use Illuminate\Contracts\Console\Kernel;
$kernel = new Kernel;
$kernel->call('refresh');
但这会返回:
Uncaught Error: Cannot instantiate interface Illuminate\Contracts\Console\Kernel
编辑:这是 OVH cron 界面的屏幕截图。 cron 任务由 OVH 自定义,只允许指向文件的完整路径 uri——该文件将执行我的工匠命令。我的问题是,我应该在这个文件中放什么,它应该是 PHP 文件还是 CMD?
【问题讨论】:
所以你不能用'crontab -e'来编辑你的crontab?如果您无法创建 cronjobs,您将如何定期执行 .file? @codedge OP 说他在 OVH 拥有一个共享主机。 OVH 允许客户在他们的 Manager 中创建 cron 作业。crontab -e
只是用最喜欢的文本编辑器打开/var/spool/cron/crontabs/<username>
的快捷方式。还有许多其他方法可以将一些内容放入该文件中。显然,脚本也可以处理它。
我更新了问题
我在 your other question 上看到您使用的是 OVH Pro。该主机通常带有 SSH 访问权限:请检查您的管理员... 用户与 FTP 相同,密码也应相同。通过 SSH,您可以使用 crontab -e
使用标准语法并遵循 Laravel 文档来运行您选择的 artisan 命令。
@Arcesilas 我对 SSH 还不够熟悉,我仍然是 FTP 新手用户,但我很快就会开始学习。目前,您的另一个答案非常令人满意,谢谢!
【参考方案1】:
您要做的是从脚本中运行特定的 Artisan 命令。
您可以通过复制artisan.php
并强制输入您想要的内容来实现此目的:
#!/usr/bin/env php
<?php
require __DIR__.'/bootstrap/autoload.php';
$app = require_once __DIR__.'/bootstrap/app.php';
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
$status = $kernel->handle(
$input = new Symfony\Component\Console\Input\ArrayInput(['command' => 'refresh']),
new Symfony\Component\Console\Output\ConsoleOutput
);
$kernel->terminate($input, $status);
exit($status);
如果您将此脚本与 artisan.php 进行比较,您会发现我刚刚强制将输入传递给 $kernel->handle()
方法。它不再从 CLI 读取输入,而是将这些参数作为一个数组。详情请见Symfony Console Component documentation。
如果您需要将参数传递给脚本,只需相应地设置输入:
$input = new Symfony\Component\Console\Input\ArrayInput([
'command' => 'refresh',
'arg_foo' => 'foo',
'--option_bar' => 42
]);
$status = $kernel->handle(
$input,
new Symfony\Component\Console\Output\ConsoleOutput
);
现在,你可以把这个脚本放在你想要的地方,它不需要通过浏览器通过网络访问(顺便说一句,它不应该)。
如果您将其放在 OVH 托管的根目录中,我的意思是不在 www,您只需非常简单地填写表格:
如果您希望您的脚本可以通过网络访问(出于明显的安全原因不建议这样做,但仍然如此),请将其放在您的 www
目录中,将路径更改为 bootstrap/autoload.php
和 bootstrap/app.php
并给出你的脚本一个不容易猜到的名字。
在OVH管理器的表单中,不要忘记在脚本路径的开头添加www/
。
无需指定php script_name
,因为当您选择PHP 版本时,管理员会为您处理。只需输入 PHP 将执行的脚本的路径即可。
【讨论】:
谢谢!这正是我一直在寻找的。非常清晰的分步说明,一切正常。 我必须再等 3 个小时才能交付赏金,但你肯定会得到它;) 谢谢!很高兴它有帮助! 在你的第一个sniper中你有这行$kernel->terminate($input, $status);
,你能解释一下$input
是从哪里来的吗?
我的错误。现在它很旧了,我没有代码了......我想我只是忘记正确复制 $status
声明中的 $input
声明(是的,另一个声明中的声明,如原始 artisan
文件)。我已经修复了 sn-p。【参考方案2】:
尝试简单:
shell_exec('php artisan refresh');
如果不起作用,请尝试为php
和artisan
添加适当的路径。
【讨论】:
这在我的本地主机上完美运行,但是当我尝试生产时,它“破坏”了网站,然后我在浏览时出现随机 500 错误。以下是来自主机的日志:FastCGI: comm with server "/home/xxx.com/public/cron-refresh.php" aborted: idle timeout (300 sec)
FastCGI: incomplete headers (0 bytes) received from server "/home/xxx.com/public/cron-refresh.php"
FastCGI: An error happend on Fastcgi processing, fallback to CGI
【参考方案3】:
如果您只想设置一个 cron 作业。请编辑 crontab 并使用“your/app/path/php artisan cron:job”直接执行您的命令。
【讨论】:
以上是关于Laravel 框架外的 Artisan::call()的主要内容,如果未能解决你的问题,请参考以下文章