2010-08-02 7 views
1

У меня есть пара php-скриптов, которые вызывается cron. Задача cron работает каждые 20 минут. Иногда сценарий заканчивает работу за несколько минут, а иногда занимает больше 20 минут.Отдельный экземпляр веб-страницы

Я хочу предотвратить состояние гонки здесь. Один из моих соображений заключается в том, чтобы использовать базу данных, устанавливая флаг при запуске страницы и удаляя флаг при выполнении задания. Но я действительно не хочу использовать базу данных.

Есть ли другое решение?

+2

Запуск вашей работы cron каждые 30 минут? ;-) – Scharron

+0

Благодарим за предложение. Он должен запускаться каждые 20 минут;) – Maximus

ответ

2

Лучший способ (который я использовал) включает сохранение идентификатора процесса в «файле блокировки».

function getLock() { 
    //First, check to see if the script is already running 
    $data = @file_get_contents('path/to/process.pid'); 
    if ($data && posix_kill($data, 0)) { 
     throw new RuntimeException(
      'Unable To Attain Lock, Another Process Is Still Running' 
     ); 
    } 
    file_put_contents('path/to/process.pid', posix_getpid()); 
} 

В основном, он читает файл, а затем пытается posix_kill ИДП, содержащийся внутри. Обратите внимание, что когда вы используете сигнал 0 в posix_kill, он просто сообщает вам, будет ли вызов успешным (что означает, что процесс запущен).

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

+0

Итак, когда работа выполнена, мне нужно просто отменить файл pid правильно? Что, если я убью php-процесс, что произойдет? – Maximus

+1

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

+0

работает отлично !! – Maximus

1

Вы можете заблокировать предварительно определенный флаг с помощью flock() и проверить, заблокирован ли этот файл перед запуском скрипта.

+1

Я бы не рекомендовал это, а что, если скрипт умрет? – thecodeassassin

+0

Да по этой причине я не использовал блокировку файлов – Maximus

+0

True - вы можете использовать какой-то тайм-аут, но он может не работать в этой часто задаваемой задаче. –

2

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

+0

Можете ли вы привести мне пример? – Maximus

+0

создайте файл при запуске задания и удалите его после завершения задания. Затем, если задание снова запущено, а другое задание выполняется, проверьте этот файл перед запуском. – jigfox

+0

Процесс пакетной очереди? Извините, я не могу. Я действительно человек VMS, и VMS включает пакетную обработку. То, что вы хотите, это небольшая программа, которая читает файл, содержащий список заданий, и когда он находит его, выполняет его, а затем удаляет из него. Это связано с некоторой синхронизацией процесса.Работы Cron не выполняют эту работу; они добавляют запрос к файлу. Кто-то, должно быть, сделал это раньше; возможно, небольшой трал в Интернете может что-то изменить. –

1

Если вы создаете файл pid, чтобы указать, что процесс запущен, обязательно проверьте, когда файл был создан, и у вас есть порог, который долгое время является длинным. Таким образом, если ваша работа умрет до того, как у нее будет возможность удалить файл pid, ваши задания не будут визжать до упора.

Смежные вопросы