Запустить скрипт только один раз?

539
26 января 2017, 04:52

В общем ситуация такая. Есть скрипт, который может работать в некоторых редких случаях больше чем интервал в cronjob, но запускать его при этом нужно каждую минуту, так как в 95% случаев он отрабатывает за несколько секунд. Нужно исключить возможность повторного запуска. Сразу оговорюсь, это бесплатный хостинг, поэтому SSH доступа нет, и мониторить процессы не получается. Остаётся лишь реализовать это средствами PHP

Пробовал так

//Статический файл который будет хранить имя временного файла
$lockFilename = __DIR__ . '/lock.dat';
//Проверяем существует ли временный файл
if (file_exists($lockFilename) && ($lock = file_get_contents($lockFilename)) && file_exists($lock)) {
    echo "Cron running now {$lock}\n";
    exit();
}
//Файл должен умереть при закрытии дескриптора
$tmpHandle = tmpfile();
//Получаем имя временного файла
$metaData = stream_get_meta_data($tmpHandle);
//Записываем имя временного файла в статический файл
file_put_contents($lockFilename, $metaData['uri']);
//Cron симуляция
echo "Cron started\n";
sleep(20);
echo "Cron stopped\n";
exit();

Но файл остаётся, если прервать скрипт через Ctrl+C

Думал решить задачу через memcache и время жизни ключа, но обратно таки бесплатный хостинг не предоставляет memcache в распоряжение

Answer 1

Вариант с блокировкой файла:

$fp = fopen("lock", "w+");
if (flock($fp, LOCK_EX | LOCK_NB)) { // выполняем  блокировку
    /*
     * Тут код который нужно выполнить 
     */ 
    flock($fp, LOCK_UN); // отпираем файл
} else { 
    echo "Не удалось получить блокировку, файл уже заблокирован!";
}
fclose($fp);
unlink("lock");

Вариант с обработкой сигналов:

declare(ticks = 1); // включить обработку сигнала    
$fp = fopen("lock", "w+");
function sigint()  { 
    // В случаях Ctrl-C
    unlink("lock");
}  
pcntl_signal(SIGINT, 'sigint');  
pcntl_signal(SIGTERM, 'sigint'); 
/*
 * Тут код который нужно выполнить 
 */  
Answer 2

Совсем аццкий вариант. Создаем таблицу с одним полем TIMESTAMP и с одной записью

$conn = new mysqli(....);
$conn->begin_transaction();
$conn->query('UPDATE dummy SET stamp=NOW()');
......
//самая последняя строка
$conn->commit();
$conn->close();

При аварийном завершении скрипта будет rollback и снятие блокировки с таблицы

READ ALSO
Побитовый сдвиг

Побитовый сдвиг

Здравствуйте! Пишу скрипт на phpЕсть числа: 16359391 15382371 7177275 15318085 16431130

388
Генерация sitemap.xml в Wordpress без плагина

Генерация sitemap.xml в Wordpress без плагина

Как генерировать sitemapxml в Wordpress без плагина? Подскажите в каком направлении двигаться

369
Добавить автопрокрутку на слайдер

Добавить автопрокрутку на слайдер

У меня вот такой вопрос, как на этом слайдере сделать автопрокрутку?

649