Cron في Linux: التاريخ والاستخدام والجهاز

Cron في Linux: التاريخ والاستخدام والجهاز

كتب الكلاسيكية أن الساعات السعيدة لا يتم مراعاتها. في تلك الأوقات العصيبة ، لم يكن هناك مبرمجون أو يونكس حتى الآن ، ولكن في هذه الأيام ، يعرف المبرمجون على وجه اليقين: بدلاً من ذلك ، سيتتبع cron الوقت.

أدوات سطر الأوامر هي ضعف وروتين بالنسبة لي. يتم تشغيل sed، awk، wc، cut والبرامج القديمة الأخرى بواسطة سكربتات على خوادمنا يوميًا. تم تصميم العديد منها كمهام لـ cron ، المجدول من السبعينيات.

لقد استخدمت cron بشكل سطحي لفترة طويلة ، دون الخوض في التفاصيل ، ولكن ذات يوم ، واجهت خطأً عند تشغيل النص ، قررت النظر فيه بدقة. هذه هي الطريقة التي ظهرت بها هذه المقالة ، والتي تعرفت خلالها على POSIX crontab ، وخيارات cron الرئيسية في توزيعات Linux الشائعة ، وتصميم بعضها.

هل تستخدم Linux وتقوم بتشغيل المهام في cron؟ هل أنت مهتم بهندسة تطبيقات النظام في Unix؟ ثم نحن في طريقنا!

محتوى

أصل الأنواع

يعد التنفيذ الدوري لبرامج المستخدم أو النظام ضرورة واضحة في جميع أنظمة التشغيل. لذلك ، أدرك المبرمجون الحاجة إلى الخدمات التي تسمح بالتخطيط المركزي وتنفيذ المهام لفترة طويلة جدًا.

تتبع أنظمة التشغيل الشبيهة بـ Unix نسبها إلى الإصدار 7 من Unix ، الذي تم تطويره في السبعينيات من القرن الماضي في Bell Labs ، بما في ذلك Ken Thompson الشهير. تم شحن الإصدار 70 من نظام Unix أيضًا مع cron ، وهي خدمة لتشغيل مهام المستخدم المتميز بانتظام.

يعد cron الحديث النموذجي برنامجًا بسيطًا ، ولكن خوارزمية الإصدار الأصلي كانت أبسط: استيقظت الخدمة مرة واحدة في الدقيقة ، واقرأ جدولًا يحتوي على مهام من ملف واحد (/ etc / lib / crontab) وتم تنفيذه للمستخدم المتميز تلك المهام التي كان يجب إكمالها في الدقيقة الحالية.

بعد ذلك ، تم شحن إصدارات محسّنة من الخدمة البسيطة والمفيدة مع جميع أنظمة التشغيل الشبيهة بـ Unix.

تم تضمين الأوصاف المعممة لتنسيق crontab والمبادئ الأساسية للأداة المساعدة في عام 1992 في المعيار الرئيسي لأنظمة التشغيل الشبيهة بيونكس - POSIX - وبالتالي أصبح cron من المعيار الفعلي هو المعيار القانوني.

في عام 1987 ، أصدر Paul Vixie ، بعد استطلاع آراء مستخدمي Unix حول رغبات cron ، إصدارًا آخر من البرنامج الخفي الذي أصلح بعض مشكلات cron التقليدية ووسع بناء جملة ملفات الجدول.

من خلال الإصدار الثالث من Vixie cron بدأ في تلبية متطلبات POSIX ، بالإضافة إلى ذلك ، كان للبرنامج ترخيصًا ليبراليًا ، أو بالأحرى ، لم يكن هناك ترخيص على الإطلاق ، باستثناء الرغبات في README: المؤلف لا يعطي ضمانات ، لا يمكن حذف اسم المؤلف ، ولا يمكن بيع البرنامج إلا مع شفرة المصدر. اتضح أن هذه المتطلبات متوافقة مع مبادئ البرمجيات الحرة ، التي كانت تكتسب شعبية في تلك السنوات ، لذا فإن بعض توزيعات Linux الرئيسية التي ظهرت في أوائل التسعينيات اتخذت Vixie cron كنظام ولا تزال تطورها.

على وجه الخصوص ، تعمل Red Hat و SUSE على تطوير تفرع من Vixie cron - cronie ، بينما يستخدم Debian و Ubuntu الإصدار الأصلي من Vixie cron مع العديد من التصحيحات.

دعنا أولاً نلقي نظرة على الأداة المساعدة crontab المعرفة من قبل المستخدم POSIX ، ثم نلقي نظرة على امتدادات بناء الجملة المقدمة في Vixie cron واستخدام أشكال Vixie cron في توزيعات Linux الشائعة. وأخيرًا ، يعمل الجليد على الكعكة على تفكيك جهاز شيطان كرون.

بوسيكس كرونتاب

بينما يعمل cron الأصلي دائمًا للمستخدم المتميز ، فمن المرجح أن يتعامل المبرمجون الحديثون مع مهام المستخدم العادية ، وهو أمر أكثر أمانًا وملاءمة.

تأتي Crons مع مجموعة من برنامجين: برنامج خفي cron يعمل باستمرار وأداة crontab سهلة الوصول للمستخدم. يسمح لك هذا الأخير بتحرير جداول المهام الخاصة بكل مستخدم في النظام ، بينما يدير البرنامج الخفي المهام من جداول المستخدم والنظام.

В معيار POSIX لا يتم وصف سلوك البرنامج الخفي بأي شكل من الأشكال ويتم إضفاء الطابع الرسمي على برنامج المستخدم فقط كرونتاب. إن وجود آليات لبدء مهام المستخدم ، بالطبع ، ضمني ، لكن لم يتم وصفه بالتفصيل.

هناك أربعة أشياء يمكن القيام بها عن طريق استدعاء الأداة المساعدة crontab: تحرير جدول مهام المستخدم في المحرر ، وتحميل الجدول من ملف ، وإظهار جدول المهام الحالي ، ومسح جدول المهام. أمثلة على الأداة المساعدة crontab:

crontab -e # редактировать таблицу задач
crontab -l # показать таблицу задач
crontab -r # удалить таблицу задач
crontab path/to/file.crontab # загрузить таблицу задач из файла

عند الاتصال crontab -e سيتم استخدام المحرر المحدد في متغير البيئة القياسي EDITOR.

يتم وصف المهام نفسها بالتنسيق التالي:

# строки-комментарии игнорируются
#
# задача, выполняемая ежеминутно
* * * * * /path/to/exec -a -b -c
# задача, выполняемая на 10-й минуте каждого часа
10 * * * * /path/to/exec -a -b -c
# задача, выполняемая на 10-й минуте второго часа каждого дня и использующая перенаправление стандартного потока вывода
10 2 * * * /path/to/exec -a -b -c > /tmp/cron-job-output.log

حقول السجلات الخمسة الأولى: الدقائق [1..60] ، الساعات [0..23] ، أيام الشهر [1..31] ، الأشهر [1..12] ، أيام الأسبوع [0 .. 6] حيث 0 - الاحد. الحقل الأخير ، السادس ، هو سطر سيتم تنفيذه بواسطة مترجم الأوامر القياسي.

في الحقول الخمسة الأولى ، يمكن سرد القيم مفصولة بفواصل:

# задача, выполняемая в первую и десятую минуты каждого часа
1,10 * * * * /path/to/exec -a -b -c

أو بشرطة:

# задача, выполняемая в каждую из первых десяти минут каждого часа
0-9 * * * * /path/to/exec -a -b -c

يتم تنظيم وصول المستخدم إلى جدولة المهام في POSIX من خلال ملفات cron.allow و cron.deny ، والتي تسرد ، على التوالي ، المستخدمين الذين لديهم وصول إلى crontab والمستخدمين الذين ليس لديهم وصول إلى البرنامج. لا ينظم المعيار موقع هذه الملفات بأي شكل من الأشكال.

يجب أن تجتاز البرامج المبتدئة ، وفقًا للمعيار ، أربعة متغيرات بيئة على الأقل:

  1. HOME هو الدليل الرئيسي للمستخدم.
  2. LOGNAME - تسجيل دخول المستخدم.
  3. PATH - المسار الذي يمكنك من خلاله العثور على أدوات النظام المساعدة القياسية.
  4. شل هو المسار إلى الغلاف المستخدم.

والجدير بالذكر أن POSIX لا تقول شيئًا عن مصدر قيم هذه المتغيرات.

الأكثر مبيعًا - Vixie cron 3.0pl1

السلف المشترك لمتغيرات كرون الشائعة هو Vixie cron 3.0pl1 ، الذي تم تقديمه في القائمة البريدية comp.sources.unix في عام 1992. سننظر في الميزات الرئيسية لهذا الإصدار بمزيد من التفصيل.

يأتي Vixie cron في برنامجين (كرون وكرونتاب). كالعادة ، يكون البرنامج الخفي مسؤولاً عن قراءة المهام وتشغيلها من جدول مهام النظام وجداول مهام المستخدم الفردي ، بينما تكون الأداة المساعدة crontab مسؤولة عن تحرير جداول المستخدم.

جدول المهام وملفات التكوين

يوجد جدول مهام المستخدم المتميز في / etc / crontab. يتوافق بناء جملة جدول النظام مع بناء جملة Vixie cron ، باستثناء أن العمود السادس يشير إلى اسم المستخدم الذي يتم تشغيل المهمة نيابة عنه:

# Запускается ежеминутно от пользователя vlad
* * * * * vlad /path/to/exec

توجد جداول مهام المستخدم العادية في / var / cron / tabs / username وتستخدم صيغة شائعة. عند تشغيل الأداة المساعدة crontab كمستخدم ، يتم تحرير هذه الملفات.

تتم إدارة قوائم المستخدمين الذين لديهم حق الوصول إلى crontab في ملفات / var / cron / allow و / var / cron / deny ، حيث يكفي إدخال اسم المستخدم في سطر منفصل.

بناء الجملة الموسعة

مقارنةً بـ POSIX crontab ، يحتوي حل Paul Wixey على بعض التعديلات المفيدة جدًا في بناء جملة جداول مهام الأداة المساعدة.

أصبح بناء جملة جديد للجدول متاحًا: على سبيل المثال ، يمكنك تحديد أيام الأسبوع أو الأشهر بالاسم (الإثنين والثلاثاء وما إلى ذلك):

# Запускается ежеминутно по понедельникам и вторникам в январе
* * * Jan Mon,Tue /path/to/exec

يمكنك تحديد الخطوة التي يتم من خلالها بدء المهام:

# Запускается с шагом в две минуты
*/2 * * * Mon,Tue /path/to/exec

يمكن خلط الخطوات والفترات الزمنية:

# Запускается с шагом в две минуты в первых десять минут каждого часа
0-10/2 * * * * /path/to/exec

يتم دعم البدائل البديهية للصيغة المعتادة (إعادة التشغيل ، سنويًا ، سنويًا ، شهريًا ، أسبوعيًا ، يوميًا ، منتصف الليل ، كل ساعة):

# Запускается после перезагрузки системы
@reboot /exec/on/reboot
# Запускается раз в день
@daily /exec/daily
# Запускается раз в час
@hourly /exec/daily

بيئة تنفيذ المهام

يسمح لك Vixie cron بتغيير بيئة التطبيقات التي تم إطلاقها.

لا يتم توفير متغيرات البيئة USER و LOGNAME و HOME بواسطة البرنامج الخفي فقط ، ولكنها مأخوذة من الملف باسود. يتم تعيين المتغير PATH على "/ usr / bin: / bin" ويتم تعيين متغير SHELL على "/ bin / sh". يمكن تغيير قيم جميع المتغيرات باستثناء LOGNAME في جداول المستخدم.

يتم استخدام بعض متغيرات البيئة (بشكل أساسي SHELL و HOME) بواسطة cron نفسه لبدء مهمة. إليك ما قد يبدو عليه استخدام bash بدلاً من sh الافتراضي لتشغيل مهام المستخدم:

SHELL=/bin/bash
HOME=/tmp/
# exec будет запущен bash-ем в /tmp/
* * * * * /path/to/exec

في النهاية ، سيتم تمرير جميع متغيرات البيئة المحددة في الجدول (سواء المستخدمة بواسطة cron أو التي تتطلبها العملية) إلى المهمة قيد التشغيل.

لتحرير الملفات ، يستخدم crontab المحرر المحدد في متغير البيئة VISUAL أو EDITOR. إذا لم يتم تعريف هذه المتغيرات في البيئة التي تم فيها تشغيل crontab ، فسيتم استخدام "/ usr / ucb / vi" (من المحتمل أن تكون ucb هي جامعة كاليفورنيا ، بيركلي).

cron على Debian و Ubuntu

أطلق مطورو دبيان والمشتقات نسخة معدلة بشكل كبير نسخة من Vixie cron 3.0pl1. لا توجد اختلافات في بناء جملة ملفات الجدول ؛ بالنسبة للمستخدمين ، هذا هو نفس Vixie cron. أكبر الميزات الجديدة: الدعم سيسلوغ, SELinux и برنامج الأغذية العالمي.

من التغييرات الأقل وضوحًا ، ولكن الملموسة - موقع ملفات التكوين وجداول المهام.

توجد جداول المستخدم في دبيان في الدليل / var / spool / cron / crontabs ، ولا يزال جدول النظام موجودًا - في / etc / crontab. توضع جداول المهام الخاصة بحزمة دبيان في /etc/cron.d ، حيث يقرأها عفريت cron تلقائيًا. يخضع التحكم في وصول المستخدم للملفات /etc/cron.allow و /etc/cron.deny.

الغلاف الافتراضي هو / bin / sh ، وهو في دبيان صدفة صغيرة متوافقة مع POSIX اندفاع، تم إطلاقه دون قراءة أي تكوين (في الوضع غير التفاعلي).

يتم تشغيل Cron نفسه في الإصدارات الحديثة من دبيان عبر systemd ، ويمكن العثور على تهيئة بدء التشغيل في /lib/systemd/system/cron.service. لا يوجد شيء خاص في تكوين الخدمة ، يمكن إجراء أي إدارة مهمة أكثر دقة من خلال متغيرات البيئة المعلنة مباشرة في crontab لكل مستخدم.

cronie على RedHat و Fedora و CentOS

cronie - شوكة Vixie cron الإصدار 4.1. كما هو الحال في Debian ، لم يتغير بناء الجملة ، لكنه أضاف دعمًا لـ PAM و SELinux ، والعمل في مجموعة ، ومراقبة الملفات باستخدام inotify ، وميزات أخرى.

التكوين الافتراضي موجود في الأماكن المعتادة: جدول النظام موجود في / etc / crontab ، وتضع الحزم جداولها في /etc/cron.d ، وتنتقل جداول المستخدم إلى / var / spool / cron / crontabs.

يعمل البرنامج الخفي ضمن systemd ، ويكون تكوين الخدمة هو /lib/systemd/system/crond.service.

في التوزيعات الشبيهة بـ Red Hat ، يكون بدء التشغيل الافتراضي هو / bin / sh ، وهو معيار bash. لاحظ أنه عند تشغيل مهام cron عبر / bin / sh ، يبدأ bash shell في الوضع المتوافق مع POSIX ولا يقرأ أي تكوين إضافي ، ويعمل في الوضع غير التفاعلي.

كروني في SLES و openSUSE

يستخدم توزيع SLES الألماني ومشتقاته openSUSE نفس cronie. يعمل البرنامج الخفي هنا أيضًا ضمن systemd ، ويكون تكوين الخدمة في /usr/lib/systemd/system/cron.service. التكوين: / etc / crontab، /etc/cron.d، / var / spool / cron / tabs. / bin / sh هو نفس bash الذي يعمل في الوضع غير التفاعلي المتوافق مع POSIX.

جهاز Vixie cron

لم يتغير أحفاد cron الحديثون بشكل جذري مقارنة بـ Vixie cron ، لكنهم ما زالوا يكتسبون ميزات جديدة غير مطلوبة لفهم مبادئ البرنامج. العديد من هذه الامتدادات قذرة وتخلط بين الكود. من دواعي سروري أن تقرأ شفرة المصدر الأصلية لـ cron بواسطة Paul Wixie.

لذلك ، قررت تحليل جهاز cron باستخدام مثال برنامج مشترك لكلا فرعي تطوير cron - Vixie cron 3.0pl1. سأبسط الأمثلة عن طريق إزالة ifdefs التي تجعل القراءة صعبة وحذف التفاصيل الثانوية.

يمكن تقسيم عمل الشيطان إلى عدة مراحل:

  1. تهيئة البرنامج.
  2. جمع وتحديث قائمة المهام لتشغيلها.
  3. عمل حلقة كرون الرئيسية.
  4. بدء مهمة.

لنأخذهم بالترتيب.

التهيئة

عند بدء التشغيل ، بعد التحقق من وسيطات العملية ، يقوم cron بتثبيت معالجات إشارة SIGCHLD و SIGHUP. الأول يسجل إدخالاً حول إنهاء العملية الفرعية ، والثاني يغلق واصف الملف لملف السجل:

signal(SIGCHLD, sigchld_handler);
signal(SIGHUP, sighup_handler);

يعمل برنامج cron الخفي في النظام دائمًا بمفرده ، فقط في دور المستخدم المتميز ومن دليل cron الرئيسي. تقوم الاستدعاءات التالية بإنشاء ملف قفل بمعرف PID لعملية البرنامج الخفي ، وتأكد من صحة المستخدم ، وقم بتغيير الدليل الحالي إلى الدليل الرئيسي:

acquire_daemonlock(0);
set_cron_uid();
set_cron_cwd();

تم تعيين المسار الافتراضي ، والذي سيتم استخدامه عند بدء العمليات:

setenv("PATH", _PATH_DEFPATH, 1);

علاوة على ذلك ، فإن العملية هي "daemonized": فهي تنشئ نسخة فرعية من العملية عن طريق استدعاء fork وجلسة جديدة في العملية الفرعية (عن طريق استدعاء Setsid). لم تعد هناك حاجة لعملية الوالدين - وتخرج:

switch (fork()) {
case -1:
    /* критическая ошибка и завершение работы */
    exit(0);
break;
case 0:
    /* дочерний процесс */
    (void) setsid();
break;
default:
    /* родительский процесс завершает работу */
    _exit(0);
}

يؤدي إنهاء العملية الأصلية إلى تحرير القفل في ملف القفل. بالإضافة إلى ذلك ، تحتاج إلى تحديث معرف المنتج في الملف لطفل. بعد ذلك يتم ملء قاعدة بيانات المهام:

/* повторный захват лока */
acquire_daemonlock(0);

/* Заполнение БД  */
database.head = NULL;
database.tail = NULL;
database.mtime = (time_t) 0;
load_database(&database);

ثم ينتقل كرون إلى حلقة العمل الرئيسية. ولكن قبل ذلك ، من المفيد إلقاء نظرة على تحميل قائمة المهام.

تجميع وتحديث قائمة المهام

تعتبر وظيفة load_database مسؤولة عن تحميل قائمة المهام. يتحقق من دليل crontab الرئيسي وملفات المستخدم. إذا لم تتغير الملفات والدليل ، فلن تتم إعادة قراءة قائمة المهام. خلاف ذلك ، تبدأ قائمة مهام جديدة في التكوين.

تحميل ملف نظام بأسماء ملفات وجداول خاصة:

/* если файл системной таблицы изменился, перечитываем */
if (syscron_stat.st_mtime) {
    process_crontab("root", "*system*",
    SYSCRONTAB, &syscron_stat,
    &new_db, old_db);
}

تحميل جداول مخصصة في حلقة:

while (NULL != (dp = readdir(dir))) {
    char    fname[MAXNAMLEN+1],
            tabname[MAXNAMLEN+1];
    /* читать файлы с точкой не надо*/
    if (dp->d_name[0] == '.')
            continue;
    (void) strcpy(fname, dp->d_name);
    sprintf(tabname, CRON_TAB(fname));
    process_crontab(fname, fname, tabname,
                    &statbuf, &new_db, old_db);
}

بعد ذلك ، يتم استبدال قاعدة البيانات القديمة بقاعدة جديدة.

في الأمثلة أعلاه ، يتحقق استدعاء process_crontab من وجود مستخدم مطابق لاسم ملف الجدول (ما لم يكن المستخدم المتميز) ثم يستدعي load_user. يقرأ الأخير بالفعل الملف نفسه سطرًا بسطر:

while ((status = load_env(envstr, file)) >= OK) {
    switch (status) {
    case ERR:
        free_user(u);
        u = NULL;
        goto done;
    case FALSE:
        e = load_entry(file, NULL, pw, envp);
        if (e) {
            e->next = u->crontab;
            u->crontab = e;
        }
        break;
    case TRUE:
        envp = env_set(envp, envstr);
        break;
    }
}

هنا إما يتم تعيين متغير البيئة (سلاسل مثل VAR = القيمة) بواسطة وظائف load_env / env_set ، أو يتم قراءة وصف المهمة (* * * * * / path / to / exec) بواسطة دالة load_entry.

كيان الإدخال الذي يعيده load_entry هو مهمتنا ، والتي يتم وضعها في قائمة المهام العامة. في الوظيفة نفسها ، يتم إجراء تحليل مطول لتنسيق الوقت ، لكننا مهتمون أكثر بتكوين متغيرات البيئة ومعلمات بدء المهمة:

/* пользователь и группа для запуска задачи берутся из passwd*/
e->uid = pw->pw_uid;
e->gid = pw->pw_gid;

/* шелл по умолчанию (/bin/sh), если пользователь не указал другое */
e->envp = env_copy(envp);
if (!env_get("SHELL", e->envp)) {
    sprintf(envstr, "SHELL=%s", _PATH_BSHELL);
    e->envp = env_set(e->envp, envstr);
}
/* домашняя директория */
if (!env_get("HOME", e->envp)) {
    sprintf(envstr, "HOME=%s", pw->pw_dir);
    e->envp = env_set(e->envp, envstr);
}
/* путь для поиска программ */
if (!env_get("PATH", e->envp)) {
    sprintf(envstr, "PATH=%s", _PATH_DEFPATH);
    e->envp = env_set(e->envp, envstr);
}
/* имя пользовтеля всегда из passwd */
sprintf(envstr, "%s=%s", "LOGNAME", pw->pw_name);
e->envp = env_set(e->envp, envstr);

مع قائمة المهام الفعلية ، تعمل الحلقة الرئيسية.

الحلقة الرئيسية

عمل cron الأصلي من الإصدار 7 Unix بكل بساطة: أعاد قراءة التكوين في حلقة ، وبدأ مهام الدقيقة الحالية بصفته المستخدم المتميز ، وينام حتى بداية الدقيقة التالية. يتطلب هذا الأسلوب البسيط في الأجهزة القديمة موارد كثيرة جدًا.

في SysV ، تم اقتراح نسخة بديلة حيث ينام البرنامج الخفي إما حتى أقرب دقيقة يتم تحديد المهمة لها ، أو لمدة 30 دقيقة. استهلكت موارد إعادة قراءة التكوين وفحص المهام في هذا الوضع أقل ، ولكن أصبح من غير الملائم تحديث قائمة المهام بسرعة.

عاد Vixie cron إلى فحص قوائم المهام مرة واحدة في الدقيقة ، لأنه بحلول نهاية الثمانينيات كان هناك المزيد من الموارد على أجهزة Unix القياسية:

/* первичная загрузка задач */
load_database(&database);
/* запустить задачи, поставленные к выполнению после перезагрузки системы */
run_reboot_jobs(&database);
/* сделать TargetTime началом ближайшей минуты */
cron_sync();
while (TRUE) {
    /* выполнить задачи, после чего спать до TargetTime с поправкой на время, потраченное на задачи */
    cron_sleep();

    /* перечитать конфигурацию */
    load_database(&database);

    /* собрать задачи для данной минуты */
    cron_tick(&database);

    /* перевести TargetTime на начало следующей минуты */
    TargetTime += 60;
}

تشارك وظيفة cron_sleep بشكل مباشر في تنفيذ المهام ، وتستدعي الوظائف job_runqueue (تعداد المهام وبدءها) و do_command (بدء كل مهمة فردية). الوظيفة الأخيرة تستحق التحليل بمزيد من التفصيل.

بدء مهمة

تتم وظيفة do_command بأسلوب Unix الجيد ، أي أنها تقوم بعمل شوكة لتنفيذ مهمة بشكل غير متزامن. تستمر العملية الرئيسية في تشغيل المهام ، بينما تقوم العملية الفرعية بإعداد عملية المهمة:

switch (fork()) {
case -1:
    /*не смогли выполнить fork */
    break;
case 0:
    /* дочерний процесс: на всякий случай еще раз пробуем захватить главный лок */
    acquire_daemonlock(1);
    /* переходим к формированию процесса задачи */
    child_process(e, u);
    /* по завершению дочерний процесс заканчивает работу */
    _exit(OK_EXIT);
    break;
default:
    /* родительский процесс продолжает работу */
    break;
}

هناك الكثير من المنطق في عملية child_process: فهي تأخذ الإخراج القياسي وتدفقات الأخطاء على نفسها ، بحيث يمكن إرسالها بعد ذلك إلى البريد (إذا تم تحديد متغير البيئة MAILTO في جدول المهام) ، وأخيراً ، ينتظر لإكمال العملية الرئيسية للمهمة.

تتكون عملية المهمة من شوكة أخرى:

switch (vfork()) {
case -1:
    /* при ошибки сразу завершается работа */
    exit(ERROR_EXIT);
case 0:
    /* процесс-внук формирует новую сессию, терминал и т.д.
     */
    (void) setsid();

    /*
     * дальше многословная настройка вывода процесса, опустим для краткости
     */

    /* смена директории, пользователя и группы пользователя,
     * то есть процесс больше не суперпользовательский
     */
    setgid(e->gid);
    setuid(e->uid);
    chdir(env_get("HOME", e->envp));

    /* запуск самой команды
     */
    {
        /* переменная окружения SHELL указывает на интерпретатор для запуска */
        char    *shell = env_get("SHELL", e->envp);

        /* процесс запускается без передачи окружения родительского процесса,
         * то есть именно так, как описано в таблице задач пользователя  */
        execle(shell, shell, "-c", e->cmd, (char *)0, e->envp);

        /* ошибка — и процесс на запустился? завершение работы */
        perror("execl");
        _exit(ERROR_EXIT);
    }
    break;
default:
    /* сам процесс продолжает работу: ждет завершения работы и вывода */
    break;
}

هذا ، بشكل عام ، هو كرون كله. لقد حذفت بعض التفاصيل المثيرة للاهتمام ، على سبيل المثال ، حساب المستخدمين عن بُعد ، لكنني أوجزت الشيء الرئيسي.

خاتمة

Cron هو برنامج بسيط ومفيد بشكل مدهش ، تم إنشاؤه وفقًا لأفضل تقاليد عالم Unix. إنها لا تفعل أي شيء إضافي ، لكنها كانت تؤدي وظيفتها بشكل ملحوظ منذ عدة عقود. استغرق الأمر أقل من ساعة لمراجعة الكود الخاص بالإصدار الذي يأتي مع Ubuntu ، وقد استمتعت كثيرًا! آمل أن أتمكن من مشاركتها معك.

لا أعرف شيئًا عنك ، لكنني حزين قليلاً لإدراك أن البرمجة الحديثة ، مع ميلها إلى التعقيد المفرط والإفراط في التجريد ، لم تعد مواتية لمثل هذه البساطة لفترة طويلة.

هناك العديد من البدائل الحديثة لـ cron: تسمح لك مؤقتات النظام بتنظيم الأنظمة المعقدة ذات التبعيات ، في fcron يمكنك تنظيم استهلاك الموارد للمهام بشكل أكثر مرونة. لكن شخصيًا ، أبسط كرونتاب كان دائمًا كافياً بالنسبة لي.

باختصار ، أحب Unix ، واستخدم برامج بسيطة ، ولا تنس قراءة Mana لمنصتك!

المصدر: www.habr.com

إضافة تعليق