如何每天执行一次查询并使用cron将结果输出到平面文件?

时间:2009-02-03 18:04:48

标签: php mysql cron

我有一个 PHP / MySQL 网站,我想输出主页上数据库/表中的条目数,但我不希望每次都进行此查询用户点击主页。我希望它每天自动运行一次并将查询结果输出到一个平面文件,然后我可以将其包含在内。我认为应该减少负荷。

我以前从未做过cron工作,也不熟悉Unix系统/命令。我的网站是一个拥有Plesk控制面板的ISP,我看到一个“crontab”部分,可以让我设置cron作业。

我不太确定要输入什么“命令”。我可以很好地制定查询,但不确定如何将结果输出到我可以通过PHP包含的平面文件。另外,理想情况下,平面文件将出现在Web根目录(与站点的其余部分)并且每天都会覆盖自己,我不想在年底使用365个平面文件。

5 个答案:

答案 0 :(得分:5)

您应该编写一个独立的PHP脚本来完成所有工作,并将其添加到您的crontab中,如下所示:

0 2 * * * cd /path/to/script; /usr/bin/php daily.php 1> output.txt 2> errors.log

每隔凌晨2点,您的daily.php脚本就会运行,输出位于output.txt,生成的任何错误(启用display_errors)都会在errors.log中结束。与将查询直接放入cron相比,这有一些优点:

  • 您不需要将您的mysql连接详细信息放入cron
  • 如果您需要,您可以包含任何网站的PHP包含文件
  • 您可以独立测试脚本,而无需等待cron运行它。

在PHP页面中包含数据的最简单,最安全的方法可能是serialize()来自查询的一系列结果,然后在需要时反序列化():

// daily.php
$data = array(
    'rows_in_table_foo' => 2343, // replace this with a query result
    'rows_in_table_bar' => 4321, // replace this with a query result
    );
echo serialize($data);
exit 0;

......并阅读它......

// index.php
$data = unserialize(file_get_contents('output.txt'));

答案 1 :(得分:2)

如果没有进一步了解您的托管系统,这可能有点棘手。如果有一个mysql命令行客户端可用,您可以尝试这样的事情:

/usr/bin/mysql -u db_user --password=db_password -e "SELECT COUNT(*) INTO OUTFILE '/tmp/myoutfile.txt' FROM my_table;" my_database

请注意,您必须在此调用中替换“db_user”,“db_password”等内容。另请注意,/usr/bin恰好是客户端在我的系统上的目录。它可能在您的托管平台上有所不同。

如果Web前端允许您直接执行shell命令,我会首先尝试这种方式,因为如果出现错误或丢失,这应该会给您更好的反馈。

如果您对编写PHP感觉更舒服,另一种解决方案是编写一个小的PHP脚本来完成创建/更新文件的工作,并在您的crontab中调用该脚本:

/path/to/php/bin/php /path/to/my/phpscript.php

当然,这取决于系统上可用的PHP命令行版本。

答案 2 :(得分:1)

对于你问题的crontab部分,你可以在你的crontab中添加这样的东西(使用命令“crontab -e”编辑它):

0 0 * * * COMMAND TO EXECTUTE QUERY > THE_FILE

每天只执行查询并将其结果传递给THE_FILE,并将其内容覆盖。

crontab条目的格式为:

minutes hours day_of_month month day_of_week COMMAND

答案 3 :(得分:0)

首先关闭它的名为“cron”并且它很容易实现..查看一些关于它的信息:http://en.wikipedia.org/wiki/Cron和入门指南:http://www.unixgeeks.org/security/newbie/unix/cron-1.html

您希望在此网站上看到多少流量?我不明白为什么在大多数情况下解雇查询会是个大问题......

  • 尼古拉斯

答案 4 :(得分:0)

总结一下你的问题。你想缓存查询结果,你是怎么做到的?

在回答问题之前,您提出了一个解决方案(存储在平面文件中)。当然,你可以做到这一点。但是,如果要创建一些基础结构,为什么不编写缓存数据类并缓存各种内容。它可以有3个属性

- 缓存项目名称 - 缓存项目值 - 缓存项目上次更新时间戳

添加几个功能

function loadCachedData($itemName);

//see if more time has passed than in the cache expiration window 
function isLoadedDataFresh($expirationWindowInSeconds);

function getLoadedItemValue();

function storeCacheValueForItem($itemName, $value);

您必须编写查询以选择项目,因此在您的控制器中,只需执行以下操作:

$cacheHandle = new Cache();

$cacheHandler->loadCachedData('whateverMyVarIs');

$displayValue = '';
if($cacheHandler->isLoadedDataFresh(60 * 60 * 24) ) //sec*min*hour = 1 day
{
    $displayValue = $cacheHandler->getLoadedItemValue();
}
else
{
    //update the display value here with your real query
    $displayValue = doMyStuff();
    $cacheHandler->storeCacheValueForItem('whateverMyVarIs', $displayValue);

}

当然,你必须清除那些代码的地狱,将你的到期时间窗口变成常量,然后实现这个类,但这不应该太难。另外,你已经拥有了一个数据库..只需用它来支持缓存类,然后缓存掉!或者如果你想使用更好的工具进行快速缓存,请使用memcached !! http://www.danga.com/memcached/

但最后,我只想问......你是否过早地进行了优化?有人真的抱怨过这个页面上的表现吗?