صيغة كرون في Airflow
تقبل الوسيطة schedule نص كرون من خمسة حقول، مرتّبة مثل سطر كرون تاب:
| الحقل | القيم المسموحة | الرموز الخاصة |
|---|---|---|
| الدقيقة | 0–59 | , - * / |
| الساعة | 0–23 | , - * / |
| يوم الشهر | 1–31 | , - * ? / L W |
| الشهر | 1–12 أو JAN–DEC | , - * / |
| يوم الأسبوع | 0–7 أو SUN–SAT (0 و7 = الأحد) | , - * ? / L # |
الرموز الخاصة
| الرمز | المعنى |
|---|---|
@ | الاختصارات: @hourly و@daily و@weekly و@monthly و@quarterly (0 0 1 */3 *) و@yearly. ويشغّل @once الـ DAG مرة واحدة فقط، ويبدأ @continuous تشغيلًا جديدًا فور انتهاء السابق، أما schedule=None فيترك الـ DAG للتشغيل اليدوي أو عبر الـ API. |
L | آخر يوم في الشهر في حقل يوم الشهر: 0 0 L * *. أما في حقل يوم الأسبوع فتضع croniter الرمز L أولًا، فـ L5 تعني آخر جمعة في الشهر، وصيغة Quartz 5L مرفوضة. |
# | ترتيب اليوم في الشهر: MON#1 أول إثنين، و5#3 ثالث جمعة. |
W | أقرب يوم عمل إلى تاريخ معيّن: 15W، ويُكتب مع يوم واحد فقط، لا مع قائمة أو نطاق. |
? | مثل *، ويُقبل وحده في أي من حقلي اليوم. |
/ | خطوة التكرار: */30 في حقل الدقائق يعمل عند الدقيقتين 0 و30، و0 */4 * * * كل أربع ساعات بدءًا من منتصف الليل. |
أمثلة على كرون Airflow
اضغط على أي تعبير لتحميله في المولّد أعلاه.
| التعبير | الجدول الزمني |
|---|---|
| في تمام الساعة 12:00 ص. | |
| في تمام الساعة 6:00 ص. | |
| في تمام الساعة 6:00 ص، من الإثنين إلى الجمعة. | |
| كل 30 دقيقة. | |
| عند الدقيقة 0 من كل ساعة، كل 4 ساعات. | |
| في تمام الساعة 12:00 ص، في اليوم 1 من الشهر، في أشهر يناير، أبريل، يوليو وأكتوبر فقط. | |
| في تمام الساعة 12:00 ص، في آخر يوم من الشهر. | |
| في تمام الساعة 9:00 ص، في أول إثنين من الشهر. | |
| في تمام الساعة 6:00 م، في آخر جمعة من الشهر. | |
| في تمام الساعة 9:00 ص، في اليوم 1 من الشهر أو يوم الإثنين. | |
| مرة واحدة فقط: ينشئ Airflow تشغيلًا واحدًا ثم لا يجدول الـ DAG مرة أخرى. | |
| باستمرار: يبدأ تشغيل جديد فور انتهاء التشغيل السابق. |
متى يعمل جدول الكرون في Airflow فعلًا؟
- في Airflow 3 يستخدم نص الكرون
CronTriggerTimetable: فالتعبير0 6 * * 1-5يبدأ تشغيلًا الساعة 06:00 من الإثنين إلى الجمعة، والتاريخ المنطقي (logical date) للتشغيل هو اللحظة نفسها. - أما في Airflow 2، وفي Airflow 3 عند ضبط
[scheduler] create_cron_data_intervals = True، فيستخدم النصCronDataIntervalTimetable، ويبدأ كل تشغيل عند نهاية فترة بياناته. فالتشغيل المؤرَّخ بيوم الجمعة 06:00 يغطي الفترة من الجمعة إلى الإثنين، لذا يبدأ يوم الإثنين الساعة 06:00. - إذا حُدّد حقلا اليوم معًا يبدأ التشغيل عند تطابق أيٍّ منهما كما في كرون تاب: فالتعبير
0 9 1 * 1يعمل في اليوم الأول من الشهر وفي كل إثنين. - تتبع المواعيد المنطقة الزمنية لـ
start_dateبما في ذلك التوقيت الصيفي. وإذا كانstart_dateبلا منطقة زمنية فيُستخدم[core] default_timezone، وهو UTC ما لم تغيّره. - القيمة الافتراضية لـ
catchupفي Airflow 3 هيFalse، فتفعيل الـ DAG لا يعوّض التشغيلات الفائتة، بينما كانت القيمة الافتراضية في Airflow 2 هيTrue.
الاستخدام في DAG
مرّر التعبير إلى schedule، فالمنطقة الزمنية لـ start_date هي التي تحدّد موعد التشغيل:
import pendulum
from airflow.sdk import dag, task
@dag(
schedule="0 6 * * 1-5",
start_date=pendulum.datetime(2026, 1, 1, tz="Asia/Riyadh"),
catchup=False,
)
def weekday_report():
@task
def build_report():
...
build_report()
weekday_report()
ولتثبيت موعد بدء التشغيل مهما كان إصدار Airflow أو إعداداته، مرّر جدولًا زمنيًا (timetable) بدلًا من النص:
from airflow.sdk import CronDataIntervalTimetable, CronTriggerTimetable
# Starts at 06:00; the logical date is 06:00 (Airflow 3 default)
schedule=CronTriggerTimetable("0 6 * * 1-5", timezone="Asia/Riyadh")
# Each run covers the interval that just ended (Airflow 2 default)
schedule=CronDataIntervalTimetable("0 6 * * 1-5", timezone="Asia/Riyadh")
في Airflow 2 استورد dag وtask من airflow.decorators، والجداول الزمنية من airflow.timetables.trigger وairflow.timetables.interval. أما schedule_interval المهمل منذ Airflow 2.4 فقد أُزيل في Airflow 3، فاستخدم schedule.
الأسئلة الشائعة
لماذا لم يعمل الـ DAG في Airflow في الموعد المحدد؟
مع الجدول الزمني القائم على فترات البيانات (الافتراضي في Airflow 2) يبدأ التشغيل عند انتهاء فترته: فتشغيل @daily الخاص بيوم 1 مارس يبدأ في منتصف ليل 2 مارس. وتأكّد أيضًا من أن start_date في الماضي، وأن الـ DAG غير موقوف مؤقتًا، ومن المنطقة الزمنية لـ start_date.
ما الفرق بين @once و@continuous وNone؟
ينشئ @once تشغيلًا واحدًا ثم لا يجدول الـ DAG مرة أخرى. ويبدأ @continuous تشغيلًا جديدًا فور انتهاء السابق، ويتطلب max_active_runs=1. أما schedule=None فلا ينشئ أي تشغيل، فلا يعمل الـ DAG إلا عند تشغيله يدويًا أو عبر الـ API.
هل يدعم Airflow الرموز L وW و# في تعبيرات الكرون؟
نعم، لأن Airflow يحلّل الكرون بمكتبة croniter: فالتعبير 0 0 L * * يعني آخر يوم في الشهر، و0 9 * * MON#1 أول إثنين، و0 18 * * L5 آخر جمعة. أما صيغ Quartz مثل 5L وLW وL-2 فمرفوضة.
ما المنطقة الزمنية لجدول الكرون في Airflow؟
المنطقة الزمنية لـ start_date الخاص بالـ DAG. فمع pendulum.datetime(2026, 1, 1, tz="Asia/Riyadh") يعمل التعبير 0 6 * * * الساعة 06:00 بتوقيت الرياض. وإذا كان start_date بلا منطقة زمنية فيُستخدم [core] default_timezone، وهو UTC افتراضيًا.
مولدات كرون لمنصات أخرى
*/15 8-18 * * 1-5
مولد تعبيرات كرون Quartz
0 0 8 ? * MON-FRI
مولد تعبيرات كرون لـ Spring
0 0 8 * * MON-FRI
مولد تعبيرات كرون لـ AWS
0 8 ? * MON-FRI *
مولد تعبيرات كرون لـ Jenkins
H 2 * * 1-5
مولد تعبيرات كرون لـ Salesforce
0 0 8 ? * MON-FRI
مولد تعبيرات كرون لـ Hangfire
0 8 * * 1-5
مولد تعبيرات node-cron
0 30 8 * * 1-5