Назад | Перейти на главную страницу

Оценить выражение cron

Есть ли инструмент командной строки, который просто оценит выражение cron и вернет ответ типа bool, если он должен работать прямо сейчас? Я ищу что-нибудь, что можно использовать в качестве утилиты в другом сценарии bash. Примерно так:

run_script=$(/tools/evaluate-cron-expression "02 4 * * *")
if [ "$run_script" -eq "1" ] # etc etc

Я знаю, я могу просто настроить реальное задание cron, но я играю с идеей обернуть все мои запланированные сценарии в другой сценарий.

Вы можете найти класс, который занимается этим здесь: http://www.phpclasses.org/package/641-PHP-Compares-timestamps-with-crontab-style-specifiers.html

Я использую этот класс около 7 лет. Он работал безупречно.

версия python из идеи php, спасибо!

import datetime

VALID_RANGES = {
    'min': '0-59',
    'hour': '0-23',
    'day': '1-31',
    'mon': '1-12',
    'week': '0-6',
}


def is_cron_time(sc: str, time_now: datetime.datetime = datetime.datetime.now()) -> bool:

    cron_l = sc.split(' ')
    if not len(cron_l) == 5:
        return False

    cron_d = {
        'min': cron_l[0],
        'hour': cron_l[1],
        'day': cron_l[2],
        'mon': cron_l[3],
        'week': cron_l[4]
    }

    time_now_d = {
        'min': time_now.minute,
        'hour': time_now.hour,
        'day': time_now.day,
        'mon': time_now.month,
        'week': time_now.weekday()
    }

    for part, val in cron_d.items():
        if val == '*':
            continue
        values = []
        """For patters like 0-23/2"""
        if '/' in val:
            rng, steps = val.split('/')
            if rng == '*':
                rng = VALID_RANGES[part]
            start, stop = [int(s) for s in rng.split('-')]
            values = list(range(start, stop, int(steps)))
        else:
            """For patters like :
            2
            2,5,8
            2-23
            """
            for v in val.split(','):
                if v == '*':
                    # should never happen
                    break
                if '-' in v:
                    start, stop = [int(s) for s in v.split('-')]
                    values = list(range(int(start), int(stop)))
                else:
                    values.append(int(v))

        if time_now_d[part] not in values:
            return False
    return True


def test():
    DT = datetime.datetime
    _now = DT.now()
    tests = [
        {'cron': '* * * * *', 'dt': _now, 'ass': True},
        {'cron': '0 * * * *', 'dt': DT(_now.year, _now.month, _now.day, _now.hour, 0), 'ass': True},
        {'cron': '2 * * * *', 'dt': DT(_now.year, _now.month, _now.day, _now.hour, 10), 'ass': False},
        {'cron': '*/2 * * * *', 'dt': DT(_now.year, _now.month, _now.day, _now.hour, 10), 'ass': True},
        {'cron': '2-15 * * * *', 'dt': DT(_now.year, _now.month, _now.day, _now.hour, 10), 'ass': True},
    ]
    for cron, dt, ass in [t.values() for t in tests]:
        assert is_cron_time(cron, dt) is ass, f'{cron} fail on {dt}'


test()