共享主机上的 CodeIgniter Cron 作业?
Posted
技术标签:
【中文标题】共享主机上的 CodeIgniter Cron 作业?【英文标题】:CodeIgniter Cron Job on Shared Hosting? 【发布时间】:2012-01-10 01:30:26 【问题描述】:我正在尝试学习如何使用 CodeIgniter 完成我的第一份 cron 工作。过去,使用 CI 执行此操作的唯一方法似乎是使用 wget
命令而不是 php
。
不过,CodeIgniter User Guide 表示现在您可以从命令行执行此操作,例如通过运行:
$ cd /path/to/project;
$ php index.php controller method
在我的本地设置中使用终端非常有用。但是当我在共享主机上的 cPanel 的 cron 部分中使用类似的命令时,该任务只会返回 index.php
的内容。
我不完全确定 cPanel 对这个命令做了什么,所以不确定它是否在使用命令行。
谁能解释一下我如何能够使用 CodeIgniter 在共享主机上设置 cron 作业?
以下是 CodeIgniter 用户指南中的示例代码:
tools.php
public function message($to = 'World')
echo "Hello $to!".PHP_EOL;
?>
【问题讨论】:
你的控制器方法是做什么的? 现在我只是在尝试 CodeIgniter 用户指南中的 Hello World 示例。为什么,这会如何影响答案? 【参考方案1】:这将取决于您的主机。如果您不小心,Cron 作业可能真的搞砸了,所以很多共享主机都不允许这样做。您可能需要在某个虚拟容器(如 VPS、virtuozo 等)上执行此操作。这不是 CodeIgniter 问题,而是托管服务提供商问题。先给他们打电话。
【讨论】:
虽然我确定你是对的,但我可以使用普通的 PHP 运行一个 cron 作业,并将文件放在 CodeIgniter 根目录中。但我觉得使用 CodeIgniter 比单独使用 PHP 要舒服得多。 好的,很高兴知道。在您的 cron 定义中,您使用的是 php 二进制文件的完整路径吗?此外,请确保您没有引用 $_SERVER 或任何未在 CLI 中定义的全局变量。我要检查的最后一件事是 gzip 是否搞砸了你的输出。我敢肯定还有更多,但这些是我脑海中的第一个......【参考方案2】:我们解决了这个确切的问题如下:
-
设置一个由 cron 调度的普通 php 文件。与 codeigniter 无关
在其中,您可以发出 fsocket 或 curl 请求来执行常规 CodeIgniter 调用,就像您从 Web 执行的操作一样。
这是一个例子(比如 cron.php)
#!/usr/local/bin/php.cli
<?php
DEFINE('CRON_CALL_URL','https://my_server/'); //
DEFINE('CRON_HTTPS_PORT', 443); // port to use during fsocket connetion
DEFINE('CRON_SSL_PREFIX', 'ssl://'); // prefix to be used on the url when using ssl
$current_time = now();
$md5_hash = md5('somevalue'.$current_time);
$url = CRON_CALL_URL.'MYCTRL/MYMETHOD';
$parts=parse_url($url);
//
$parts['query']='md5_hash='.$md5_hash.'&time='.$current_time;
$fp = fsockopen(CRON_SSL_PREFIX.$parts['host'],
isset($parts['port'])?$parts['port']:CRON_HTTPS_PORT,
$errno, $errstr, 30);
if (!$fp)
else
if (!array_key_exists('query', $parts)) $parts['query'] = null;
$out = "POST ".$parts['path']." HTTP/1.1\r\n";
$out.= "Host: ".$parts['host']."\r\n";
$out.= "Content-Type: application/x-www-form-urlencoded\r\n";
$out.= "Content-Length: ".strlen($parts['query'])."\r\n";
$out.= "Connection: Close\r\n\r\n";
if (isset($parts['query'])) $out.= $parts['query'];
fwrite($fp, $out);
fclose($fp);
?>
注意:确保在您的 MYCTRL/MYMETHOD 函数中有
ignore_user_abort(true);
这样,当您关闭 fsocket 连接时,您的脚本仍将运行到最后。
出于各种原因,我们实际上有一堆这样的 fsocket。如果您需要确保对该控制器/方法的调用来自 cron 脚本,则需要传递一些额外的哈希值,以便只有 cron 和脚本知道它。一旦脚本被调用,它就可以访问任何 codeigniter 函数。像魅力一样工作。
【讨论】:
【参考方案3】:我在共享主机上设置了 100 多个 CI cronjob,如下所示:创建一个简短的 php 脚本,它调用 CI 控制器,就好像它是一个网络浏览器一样。
所以,script.php 包含以下内容:
script #! /usr/local/bin/php -f /home/example/public_html/script.php
<?php
get_get_contents('http:example.com/cronjob/');
?>
然后在 cPanel 中设置你的 cronjob 来调用 script.php 当它运行时 Script.php 将调用 Codeigniter Cronjob 控制器。您可以使用整个 CI 框架。
【讨论】:
【参考方案4】:如果你要像网络浏览器一样调用它,为什么不替换 cronjob 命令:
wget http://example.com/cronjob/
而不是创造新的东西或简单地
curl --suppress http://example.com/cronjob/`
【讨论】:
以上是关于共享主机上的 CodeIgniter Cron 作业?的主要内容,如果未能解决你的问题,请参考以下文章
如何为服务器上的 codeigniter 脚本设置 cron 作业
cron 命令在共享主机中无法与 DirectAdmin 一起使用