2011-01-03 36 views
14

Tôi cần phát triển hệ thống tác vụ có thể hoạt động trên các máy chủ không hỗ trợ crontab.Chức năng PHP nhận chuỗi cron và trả về dấu thời gian chạy tiếp theo

Tôi hỏi nếu có bất kỳ mã hiện tại có thể tham gia một chuỗi cron (ví dụ '0 0,12 1 */2 *' và trả lại dấu thời gian của thời gian theo lịch trình tiếp theo.

Nếu như một mã không thể được tìm thấy sau đó làm thế nào tôi nên bắt đầu với điều đó

+0

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

Trả lời

12

Bạn có thể sử dụng lớp này PHP-Parse-cron-strings-and-compute-schedules

Nó cũng sẽ tính toán theo lịch trình chạy cuối cùng

+3

cũng thấy http: // stackoverflow.com/questions/321494/calculate-when-a-cron-job-sẽ-được-thi-sau-tiếp theo-thời gian – berebidahoo

+0

Tôi sử dụng lớp PHP-Parse cron để chạy sub-crons trên hai máy chủ và tôi chưa có vấn đề duy nhất với nó – Patrick

8

sử dụng chức năng này:

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

chức năng tuyệt vời. Ở đây nó là với một phong cách mã tiêu chuẩn hơn. https://gist.github.com/goosehub/7deff7928be04ec99b4292be10b4b7b0 – Goose

+0

Tôi đã tìm thấy lỗi trong mã của bạn. Xem câu trả lời của tôi cho lời giải thích và cảm thấy tự do để áp dụng nó cho câu trả lời của bạn. – Goose

+0

@ Ngỗng, tôi nghĩ rằng "$ time [$ k] = intval ($ time [$ k]);" được rồi. – diyism

0

Trong parse_crontab chức năng:

Thay $time[$k] với intval($time[$k]) bên trong preg_replace dòng
để so sánh hai base10 số chính xác.

+0

Bạn có thể vui lòng thuật lại câu trả lời của mình không? Thật khó hiểu. Có chức năng parse_crontab nào không? Ở đâu? Làm sao? Và đó là gì về việc thay thế mã? Bạn có đề xuất điều chỉnh hàm 'parse_crontab' không? – einpoklum

1

Tôi thấy chủ nghĩa tự chế có câu trả lời tuyệt vời nhưng đã tìm thấy một lỗi nghiêm trọng.

Nếu bạn nhập thời gian cron như 0 * * * *, nó sẽ chạy ở 0 phút, 8, phút và phút thứ 9. Mã cho một điều kiện 08===0, trả về true, vì PHP diễn giải các số bắt đầu bằng 0 là bát phân, và 08 và 09 không phải là số bát phân hợp lệ để chúng được hiểu là 0. Thông tin thêm tại đây.

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

Đây là phiên bản cố định và được nhận xét tốt về mã của chủ nghĩa tự chế.

// 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

Tôi nghĩ rằng "$ time [$ k] = intval ($ time [$ k]);" là ok, tôi đã cập nhật câu trả lời của tôi, cảm ơn. – diyism

+0

@diyism 'echo intval (09);' cho 0, vì vậy rất tiếc bạn phải sử dụng '$ time [$ k] = preg_replace ('/^0 + (? = \ D) /', '', $ thời gian [$ k]); ' – Goose

0

Tôi đã viết một lớp PHP rất mạnh gọi là CalendarEvent một thời gian dài trước:

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

Nó hỗ trợ hai cú pháp mô hình khác nhau. Cron bình thường không thể xử lý các mẫu phức tạp nhất định trong khi cú pháp CalendarEvent mặc định xử lý bất kỳ mẫu lập biểu nào mà bạn có thể cần. Hỗ trợ cú pháp mẫu cron thực sự là một dự phòng (các dòng cron tiền tố có cron và một khoảng trống).

LịchEvent được viết chủ yếu dưới dạng lớp tính toán sự kiện lịch và vừa xảy ra để hỗ trợ các cơ chế "kích hoạt tiếp theo" cron. Nó thực sự được thiết kế để tính toàn bộ lịch biểu trong nhiều tháng với mục đích hiển thị lịch cho người dùng (do đó tên lớp). Tôi cũng đã sử dụng lớp này làm giải pháp trung gian để dịch sự kiện giữa các nền tảng lịch. Đó là kịch bản hiếm hơn - tôi thường xuyên sử dụng nó cho các giải pháp giống như cron-AddSchedule()/NextTrigger().

Các vấn đề liên quan