Как выполнить запрос один раз в день и вывести результаты в плоский файл с помощью cron? - PullRequest
3 голосов
/ 03 февраля 2009

У меня есть PHP / MySQL веб-сайт, на котором я хочу вывести количество записей в БД / таблице на главной странице, но я не хочу делать этот запрос каждый раз, когда пользователь попадает на домашнюю страницу. Я хочу, чтобы он автоматически запускался один раз в день и выводил результаты запроса в плоский файл, который я затем мог бы просто включить. Я полагаю, что это должно немного снизить нагрузку.

Я никогда раньше не работал cron, и я не очень хорошо знаком с системой / командами Unix. Мой сайт с интернет-провайдером, у которого есть панель управления Plesk, и я вижу раздел "crontab", который позволяет мне настраивать задания cron.

Я не совсем уверен, какую "команду" вводить. Я могу сформулировать запрос очень хорошо, но не уверен, как вывести результаты в плоский файл, который я могу включить через PHP. Кроме того, в идеале плоский файл должен отображаться в корневом веб-каталоге (вместе с остальной частью сайта) и перезаписываться каждый день, я не хочу, чтобы в конце года было 365 плоских файлов.

Ответы [ 5 ]

5 голосов
/ 04 февраля 2009

Вы должны написать автономный скрипт 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'));
2 голосов
/ 03 февраля 2009

Это может быть немного сложно получить право без дополнительных знаний о вашей хостинговой системе. Если есть клиент командной строки 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 просто является каталогом, в котором находится клиент в моей системе. Это может отличаться на вашей хостинговой платформе.

Если веб-интерфейс позволяет вам выполнять команды оболочки напрямую, я сначала попробую эту команду таким образом, поскольку это даст вам лучшую обратную связь, если что-то не так или отсутствует.

Если вы чувствуете себя более комфортно при кодировании PHP, другим решением будет написать небольшой PHP-скрипт, который выполняет работу по созданию / обновлению файла, и вызвать этот скрипт в вашем crontab:

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

Конечно, это зависит от версии PHP для командной строки, доступной в вашей системе.

1 голос
/ 03 февраля 2009

Для части 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
0 голосов
/ 04 февраля 2009

давайте подведем итоги вашего вопроса. Вы хотите кэшировать результаты запроса, как вы это делаете?

Вы предлагаете решение (сохраните в плоском файле), прежде чем ответить на свой вопрос. Так конечно, вы можете сделать это. Но если вы собираетесь создать небольшую инфраструктуру, почему бы не написать класс данных для кэширования и не кэшировать все виды вещей. Может иметь 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/

Но, наконец, я просто должен спросить ... вы преждевременно оптимизируете? Кто-то действительно жаловался на производительность на этой странице?

0 голосов
/ 03 февраля 2009

Ну, во-первых, он называется "cron" и довольно прост в реализации. Ознакомьтесь с небольшой информацией об этом: http://en.wikipedia.org/wiki/Cron и руководством по началу работы: http://www.unixgeeks.org/security/newbie/unix/cron-1.html.

Какой объем трафика вы ожидаете увидеть на этом сайте? Я не понимаю, почему в большинстве случаев запуск запроса был бы большой проблемой ...

  • Николай
...