3

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

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

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

4

5 回答 5

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()查询结果的数组,然后在需要时对其进行 unserialize():

// 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'));
于 2009-02-03T23:09:23.193 回答
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 命令行版本。

于 2009-02-03T18:18:17.710 回答
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
于 2009-02-03T18:28:01.950 回答
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);

}

当然,您必须彻底清除该代码,将到期时间窗口转换为常量,并实现该类,但这应该不会太难。另外,你已经有一个 db.. 只需用它返回缓存类,然后缓存!或者,如果您想使用更好的工具进行快速缓存,请使用 memcached!http://www.danga.com/memcached/

但最后,我只需要问...您是否过早优化?有人真的抱怨过这个页面的表现吗?

于 2009-02-04T09:17:35.803 回答
0

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

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

  • 尼古拉斯
于 2009-02-03T18:07:05.330 回答