Как запускать Cronjobs чаще, чем раз в минуту? - PullRequest
12 голосов
/ 12 января 2011

Я создал таблицу базы данных Email-Queue.Я добавлю в эту таблицу все электронные письма, которые необходимо отправить моему PHP-приложению.

Затем другой скрипт PHP будет искать все неотправленные электронные письма и отправлять их.

Я запускаю этот скрипт, используя cronjobs.К сожалению, cronjobs может работать только максимум раз в минуту.Поэтому в худшем случае пользователь должен подождать одну минуту, пока его электронная почта действительно не будет отправлена.

Моя текущая идея для обходного пути - вызвать скрипт с дополнительным параметром сна и дублировать cronjobs.

Пример:

* * * * * curl emails.php?sleep=0 >/dev/null 2>&1
* * * * * curl emails.php?sleep=10 >/dev/null 2>&1
* * * * * curl emails.php?sleep=20 >/dev/null 2>&1
* * * * * curl emails.php?sleep=30 >/dev/null 2>&1
* * * * * curl emails.php?sleep=40 >/dev/null 2>&1
* * * * * curl emails.php?sleep=50 >/dev/null 2>&1

В приведенном выше примере скриптбегать каждые 10 секунд.Первая строка скрипта emails.php будет выглядеть так:

sleep($_REQUEST['sleep']);

Ответы [ 4 ]

15 голосов
/ 16 июня 2013

Вот простой написанный мной bash-скрипт, который можно использовать с crontab для запуска чаще, чем за 1 минуту.

вы можете сохранить его как ~ / bin / runEvery.sh а затем в crontab напишите что-нибудь подобное для запуска otherScript.sh каждые 5 секунд:

*/1 * * * * ~/bin/runEvery.sh 5 otherScript.sh

Это скрипт:

#!/bin/bash

inputPeriod=$1
runCommand=$2
RUN_TIME=60
error="no"

if [ 'x'"$runCommand" != 'x' ]
then
    if [ 'x'$inputPeriod != 'x' ]
    then
        loops=$(( $RUN_TIME / $inputPeriod ))
        if [ $loops -eq 0 ]
        then
            loops=1
        fi

        for i in $(eval echo {1..$loops})
        do
            $runCommand
            sleep $inputPeriod
        done

    else
        error="yes"
    fi
else
    error="yes"
fi

if [ $error = "yes" ]
then
    echo "runEvery - runs a command every X seconds for a minute"
    echo "Usage: runEvery.sh <# in seconds < 60> <command to run>"
fi
13 голосов
/ 12 января 2011

Это должно быть сделано на уровне сценария.

// cron.php running every 10 seconds

<?php

$expireTime = time() + 60;
while (time() < $expireTime) {
     // my php logic here

     sleep(10); 
     // sleep for 10 seconds
     // you may change the sleep time to change frequency
}
9 голосов
/ 12 января 2011

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

Таким образом, вы можете просто спать / проверять электронную почту / передавать / спать и т. Д. Внутри сценария PHP, а не использовать Cron без необходимости.

Кроме того, я бы позаботился о том, чтобы несколько PHP-скриптов не работали с таблицей базы данных одновременно, либо с помощью pid-файла, либо с использованием подхода к настройке базы данных (если данный файл / настройка существует / установлен , прервать обработку) или разумно синхронизировать задание cron и ограничить максимальное время обработки сценария, проверив, как долго он выполняется до начала части цикла «проверка сообщений».

1 голос
/ 12 января 2011

Если вы делаете это каждые 10 секунд, cron просто не подходит для работы. Вам нужен скрипт, который работает непрерывно, как показано Ишем.

Вы можете зарегистрировать скрипт как сервис, поместив соответствующий скрипт запуска / остановки в /etc/init.d и включив его.

Или, если у вас есть только учетная запись пользователя, вы можете запустить ее в сеансе экрана. Тогда вы даже можете посмотреть вывод для диагностики ошибок.

...