Запуск сценария PHP каждые 5 минут и избегая условий гонки

У меня есть скрипт php, который должен запускаться раз в 5 минут. В настоящее время я использую задание cron для его запуска (и оно отлично работает), но мой хост позволяет отработать не менее 15 минут.

Поэтому мой вопрос заключается в том, могу ли я использовать посетителей для запуска каждого сценария php каждый раз 5 минут. Я легко могу записать последний раз, когда он запускался, и повторно запустить его, основываясь на прошедшем времени.

Однако меня беспокоит состояние гонки. Важно, чтобы скрипт запускался только один раз каждые 5 минут.

Мой сценарий занимает около 60 секунд. За это время пишет в пару файлов. Если скрипт запускался более одного раза, он испортил бы файлы. Кроме того, если я не получу ни одного посетителя в течение 10 минут, затем работает один раз, когда появляется следующий резистор.

Есть ли какой-нибудь стандартный способ выполнить эту задачу?

Спасибо!

7
задан Imbue 26 August 2010 в 01:33
поделиться

3 ответа

Рассматривали ли вы, чтобы ваш скрипт запускал бесконечный цикл с сна для ожидания 5 минут между итерациями?

for (;;)
{
  perform_actions();
  sleep(300);
}

В качестве альтернативы вы могли бы иметь файл (например, , is_running), и получите эксклюзивную блокировку на него в начале вашего скрипта, которая освобождается в конце. По крайней мере, так вы не сделаете ничего разрушительного.

Вы также можете объединить эти два решения.

$fp = fopen("is_running", "r+");

/* is it already running? */
if (! flock($fp, LOCK_EX | LOCK_NB)) return;

for (;;)
{
  perform_actions();
  sleep(300);
}

И тогда задание cron по-прежнему будет запускаться каждые 15 минут. Если процесс все еще запущен, он просто выйдет из строя, в противном случае он перезапустится и возобновит обновление каждые 5 минут.

6
ответ дан 6 December 2019 в 22:59
поделиться

Если вы не можете сделать то, что предложил @Brandon, я бы рекомендовал подойти к этому так же, как я делал при написании демона на PHP (не лучшее решение, но я был практически вынужден сделать это ).

В моем случае сценарий также обращался к файлу (журнала) и выполнял его обработку, после чего вставлял результаты в базу данных. Поэтому, чтобы убедиться, что у меня нет двух файлов, работающих одновременно, я создал файл «статуса», на котором скрипт получил блокировку и, если не смог сделать это, если изящно потерпел неудачу.

$fh = fopen('status_file', 'w');

/**
 * LOCK_NB is required because otherwise your script would stall until
 * a lock is aquired, queing a bunch of scripts.
 */
if(!flock($fh, LOCK_EX | LOCK_NB)) {
  exit 1; // our job is done here
}
1
ответ дан 6 December 2019 в 22:59
поделиться

Неубедительный ответ на неуместную ситуацию (провайдер, а не плакат). Запланируйте 12 заданий cron, все из которых вызывают один и тот же сценарий, каждое из которых запускается один раз в час, но вызывается с разной 5-минутной отметкой.

00 * * * * root echo "run at :00 of every hour"
05 * * * * root echo "run at :05 of every hour"
10 * * * * root echo "run at :10 of every hour"

и т. д. до :55. Но я остаюсь при своем первоначальном комментарии - найдите нового провайдера :)

4
ответ дан 6 December 2019 в 22:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: