评估 cron 表达式

评估 cron 表达式

是否有一个命令行工具可以简单地评估 cron 表达式并返回布尔响应(如果它现在应该正在运行)?我正在寻找可以用作另一个 bash 脚本中的实用程序的东西。像这样:

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

我知道,我知道,我可以设置一个真正的 cron 作业,但我正在考虑将所有计划的脚本包装在另一个脚本中。

答案1

您可以在这里找到处理此问题的课程:http://www.phpclasses.org/package/641-PHP-Compares-timestamps-with-crontab-style-specifiers.html

我已经使用这个课程大约 7 年了。它运行完美。

答案2

来自 php idea 的 python 版本,谢谢!

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()

相关内容