2011-01-03 11 views
14

Potrzebuję opracować system zadań, który powinien być w stanie pracować na serwerach, które nie obsługują crontab.Funkcja PHP, która odbiera ciąg znaków cron i zwraca następny znacznik czasu uruchomienia.

pytam czy jest jakiś istniejący kod, który może mieć ciąg cron (np „0 0,12 1 */2 *” i powrót znacznika czasu następnego uruchomienia zaplanowanego.

Jeśli taka Kod nie został znaleziony, to jak powinienem zacząć z tym

+0

http://stackoverflow.com/questions/321494/calculate-when-a-cron-job- will-be-executed-then-next-time/3453872#3453872 –

Odpowiedz

12

można użyć tej klasy PHP-Parse-cron-strings-and-compute-schedules

będzie również obliczyć ostatnio zaplanowanego ucieka

+3

Zobacz także http: // stackoverflow.com/questions/321494/calcul-when-a-cron-job-will-be-be-was-then-next-time – berebidahoo

+0

Używam klasy cron PHP-Parse do uruchamiania sub-cronów na dwóch serwerach i nie miałem pojedynczy problem z tym – Patrick

8

użyć tej funkcji:

function parse_crontab($time, $crontab) 
     {$time=explode(' ', date('i G j n w', strtotime($time))); 
      $crontab=explode(' ', $crontab); 
      foreach ($crontab as $k=>&$v) 
        {$time[$k]=intval($time[$k]); 
        $v=explode(',', $v); 
        foreach ($v as &$v1) 
          {$v1=preg_replace(array('/^\*$/', '/^\d+$/', '/^(\d+)\-(\d+)$/', '/^\*\/(\d+)$/'), 
              array('true', $time[$k].'===\0', '(\1<='.$time[$k].' and '.$time[$k].'<=\2)', $time[$k].'%\1===0'), 
              $v1 
              ); 
          } 
        $v='('.implode(' or ', $v).')'; 
        } 
      $crontab=implode(' and ', $crontab); 
      return eval('return '.$crontab.';'); 
     } 
var_export(parse_crontab('2011-05-04 02:08:03', '*/2,3-5,9 2 3-5 */2 *')); 
var_export(parse_crontab('2011-05-04 02:08:03', '*/8 */2 */4 */5 *')); 
+0

Niesamowita funkcja. Tutaj jest z bardziej standardowym stylem kodu. https://gist.github.com/goosehub/7deff7928be04ec99b4292be10b4b7b0 – Goose

+0

Znalazłem błąd w twoim kodzie. Zobacz moją odpowiedź na wyjaśnienia i nie krępuj się zastosować ją do swojej odpowiedzi. – Goose

+0

@Goose, myślę, że "$ time [$ k] = intval ($ time [$ k]);" jest w porządku. – diyism

0

W parse_crontab funkcję:

Wymień $time[$k] z intval($time[$k]) wewnątrz linii
preg_replace porównać dwa base10 numery poprawnie.

+0

Czy możesz powtórzyć swoją odpowiedź? Trudno to zrozumieć. Czy dostępna jest funkcja parse_crontab? Gdzie? W jaki sposób? A co z wymianą kodu? Sugerujesz dostosowanie funkcji 'parse_crontab'? – einpoklum

1

Znalazłem diyyzm miał świetną odpowiedź, ale znalazłem kluczowy błąd.

Jeśli wpiszesz czas cron, taki jak 0 * * * *, będzie on działał w 0 minucie, 8, minucie i 9 minucie. Kod podaje warunkowe 08===0, które zwraca wartość true, ponieważ PHP interpretuje liczby rozpoczynające się od 0 jako ósemkowe, a 08 i 09 nie są poprawnymi liczbami ósemkowymi, więc są interpretowane jako 0. Więcej informacji tutaj.

How to prevent PHP from doing octal math in conditionals? (why does 08 === 0)

Oto stałe i dobrze skomentował wersja kodu diyism użytkownika.

// Parse CRON frequency 
function parse_crontab($time, $crontab) { 
    // Get current minute, hour, day, month, weekday 
    $time = explode(' ', date('i G j n w', strtotime($time))); 
    // Split crontab by space 
    $crontab = explode(' ', $crontab); 
    // Foreach part of crontab 
    foreach ($crontab as $k => &$v) { 
     // Remove leading zeros to prevent octal comparison, but not if number is already 1 digit 
     $time[$k] = preg_replace('/^0+(?=\d)/', '', $time[$k]); 
     // 5,10,15 each treated as seperate parts 
     $v = explode(',', $v); 
     // Foreach part we now have 
     foreach ($v as &$v1) { 
      // Do preg_replace with regular expression to create evaluations from crontab 
      $v1 = preg_replace(
       // Regex 
       array(
        // * 
        '/^\*$/', 
        // 5 
        '/^\d+$/', 
        // 5-10 
        '/^(\d+)\-(\d+)$/', 
        // */5 
        '/^\*\/(\d+)$/' 
       ), 
       // Evaluations 
       // trim leading 0 to prevent octal comparison 
       array(
        // * is always true 
        'true', 
        // Check if it is currently that time, 
        $time[$k] . '===\0', 
        // Find if more than or equal lowest and lower or equal than highest 
        '(\1<=' . $time[$k] . ' and ' . $time[$k] . '<=\2)', 
        // Use modulus to find if true 
        $time[$k] . '%\1===0' 
       ), 
       // Subject we are working with 
       $v1 
      ); 
     } 
     // Join 5,10,15 with `or` conditional 
     $v = '(' . implode(' or ', $v) . ')'; 
    } 
    // Require each part is true with `and` conditional 
    $crontab = implode(' and ', $crontab); 
    // Evaluate total condition to find if true 
    return eval('return ' . $crontab . ';'); 
} 
+0

Myślę, że "$ time [$ k] = intval ($ time [$ k]);" jest ok, zaktualizowałem moją odpowiedź, dziękuję. – diyism

+0

@diyism 'echo intval (09);' daje 0, więc niestety musisz użyć '$ time [$ k] = preg_replace ('/^0 + (? = \ D) /', '', $ czas [$ k]); ' – Goose

0

Napisałem bardzo silną klasę PHP o nazwie CalendarEvent dawno temu:

https://github.com/cubiclesoft/php-misc/

Obsługuje dwa różne składnie sygnatur. Normalny cron nie może obsłużyć pewnych złożonych wzorców, podczas gdy domyślna składnia CalendarEvent obsługuje dowolny wzorzec planowania, jakiego można potrzebować. Obsługa składni wzorca cron jest w rzeczywistości funkcją zastępczą (prefiks linii cron z cron i spacją).

CalendarEvent został napisany głównie jako klasa obliczeń zdarzeń kalendarza i właśnie stał się mechanizmem "następnego uruchomienia" w stylu Cron. Jest tak naprawdę zaprojektowany do obliczania całego harmonogramu na wiele miesięcy w celu wyświetlania kalendarza użytkownikowi (stąd nazwa klasy). Używam również klasy jako pośredniego rozwiązania do tłumaczenia wydarzeń między platformami kalendarza. Jest to rzadszy scenariusz - coraz częściej korzystałem z niego w przypadku podobnych do cron rozwiązań AddSchedule()/NextTrigger().

Powiązane problemy