Cron در لینوکس: تاریخچه، استفاده و دستگاه

Cron در لینوکس: تاریخچه، استفاده و دستگاه

کلاسیک نوشت که ساعت های شاد تماشا نمی کنند. در آن دوران وحشی نه برنامه نویس وجود داشت و نه یونیکس، اما امروز برنامه نویسان با اطمینان می دانند: cron به جای آنها زمان را پیگیری می کند.

ابزارهای خط فرمان برای من هم یک ضعف و هم یک کار طاقت فرسا هستند. sed، awk، wc، cut و سایر برنامه های قدیمی هر روز توسط اسکریپت ها بر روی سرورهای ما اجرا می شوند. بسیاری از آن‌ها به‌عنوان وظایفی برای cron طراحی شده‌اند، برنامه‌ریزی که در اصل مربوط به دهه 70 است.

برای مدت طولانی از cron به صورت سطحی و بدون پرداختن به جزئیات استفاده می کردم، اما یک روز که هنگام اجرای یک اسکریپت با خطا مواجه شدم، تصمیم گرفتم آن را به طور کامل بررسی کنم. این مقاله به این شکل ظاهر شد، در حین نوشتن آن با Crontab POSIX، گزینه های اصلی cron در توزیع های محبوب لینوکس و ساختار برخی از آنها آشنا شدم.

آیا از لینوکس استفاده می کنید و وظایف cron را اجرا می کنید؟ آیا به معماری برنامه های سیستمی در یونیکس علاقه مند هستید؟ سپس ما در راه هستیم!

مقدار

منشاء گونه ها

اجرای دوره ای برنامه های کاربر یا سیستم یک ضرورت آشکار در همه سیستم عامل ها است. بنابراین، برنامه نویسان از مدت ها قبل نیاز به خدماتی را که به آنها اجازه می دهد تا به طور متمرکز وظایف را برنامه ریزی و اجرا کنند، دریافتند.

سیستم‌عامل‌های شبه یونیکس منشأ خود را به نسخه 7 یونیکس بازمی‌دارند که در دهه 70 قرن گذشته در آزمایشگاه‌های بل توسعه یافت، از جمله توسط کن تامپسون معروف. نسخه 7 یونیکس همچنین دارای cron است، سرویسی برای اجرای منظم وظایف ابرکاربر.

یک cron مدرن معمولی یک برنامه ساده است، اما الگوریتم عملیاتی نسخه اصلی حتی ساده تر بود: سرویس یک بار در دقیقه بیدار می شود، جدولی را با وظایف از یک فایل (/etc/lib/crontab) می خواند و برای superuser آن دسته از وظایفی که باید در لحظه فعلی انجام می شد.

متعاقباً، نسخه‌های بهبودیافته این سرویس ساده و مفید با تمام سیستم‌عامل‌های شبه یونیکس عرضه شد.

توضیحات کلی از فرمت crontab و اصول اولیه عملکرد ابزار در استاندارد اصلی سیستم‌عامل‌های شبه یونیکس - POSIX - در سال 1992 گنجانده شد و بنابراین کرون از یک استاندارد واقعی تبدیل به یک استاندارد قانونی شد.

در سال 1987، پل ویکسی، پس از بررسی کاربران یونیکس در مورد خواسته‌هایشان برای کرون، نسخه دیگری از دیمون را منتشر کرد که برخی از مشکلات کرون سنتی را اصلاح کرد و نحو فایل‌های جدول را گسترش داد.

با نسخه سوم Vixie cron شروع به برآورده کردن الزامات POSIX کرد، علاوه بر این، برنامه دارای مجوز لیبرال بود، یا بهتر است بگوییم هیچ مجوزی وجود نداشت، به جز خواسته های موجود در README: نویسنده تضمین نمی کند، نام نویسنده. نمی توان آن را حذف کرد، و برنامه فقط می تواند همراه با کد منبع فروخته شود. معلوم شد که این الزامات با اصول نرم‌افزار آزاد که در آن سال‌ها محبوبیت پیدا می‌کرد، سازگار است، بنابراین برخی از توزیع‌های کلیدی لینوکس که در اوایل دهه 90 ظاهر شدند، Vixie cron را به عنوان سیستم خود انتخاب کردند و هنوز هم در حال توسعه آن هستند.

به طور خاص، Red Hat و SUSE یک فورک از Vixie cron - cronie را توسعه می دهند و دبیان و اوبونتو از نسخه اصلی Vixie cron با تعداد زیادی وصله استفاده می کنند.

بیایید ابتدا با crontab ابزار کاربردی توضیح داده شده در POSIX آشنا شویم، پس از آن به پسوندهای نحو ارائه شده در Vixie cron و استفاده از تغییرات Vixie cron در توزیع‌های محبوب لینوکس خواهیم پرداخت. و در نهایت گیلاس روی کیک آنالیز دستگاه cron daemon است.

کرونتاب POSIX

اگر cron اصلی همیشه برای superuser کار می کرد، زمانبندی های مدرن اغلب با وظایف کاربران عادی سروکار دارند که ایمن تر و راحت تر است.

Cron ها به صورت مجموعه ای از دو برنامه عرضه می شوند: cron daemon دائماً در حال اجرا و ابزار 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. SHELL - مسیر به مفسر فرمان استفاده شده.

قابل توجه است که POSIX در مورد اینکه مقادیر این متغیرها از کجا آمده اند چیزی نمی گوید.

پرفروش ترین - Vixie cron 3.0pl1

جد مشترک انواع محبوب کرون Vixie cron 3.0pl1 است که در لیست پستی comp.sources.unix در سال 1992 معرفی شد. ویژگی های اصلی این نسخه را با جزئیات بیشتری بررسی خواهیم کرد.

Vixie cron در دو برنامه (cron و crontab) عرضه می شود. طبق معمول، daemon مسئول خواندن و اجرای وظایف از جدول وظایف سیستم و جداول تک تک کاربران است و ابزار crontab وظیفه ویرایش جداول کاربر را بر عهده دارد.

جدول وظایف و فایل های پیکربندی

جدول وظایف superuser در /etc/crontab قرار دارد. نحو جدول سیستم با نحو Vixie cron مطابقت دارد، با این تفاوت که ستون ششم در آن نام کاربری را نشان می دهد که از طرف او وظیفه راه اندازی شده است:

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

جداول وظایف کاربر معمولی در /var/cron/tabs/username قرار دارند و از همان نحو استفاده می کنند. هنگامی که برنامه crontab را به عنوان کاربر اجرا می کنید، این فایل ها ویرایش می شوند.

لیست کاربرانی که به crontab دسترسی دارند در فایل های /var/cron/allow و /var/cron/deny مدیریت می شوند، جایی که شما فقط باید نام کاربری را در یک خط جداگانه وارد کنید.

نحو توسعه یافته

در مقایسه با Crontab POSIX، راه حل Paul Vixey شامل چندین تغییر بسیار مفید در نحو جداول وظیفه ابزار است.

یک نحو جدول جدید در دسترس است: به عنوان مثال، می توانید روزهای هفته یا ماه ها را با نام (دوشنبه، سه شنبه و غیره) مشخص کنید:

# Запускается ежеминутно по понедельникам и вторникам в январе
* * * 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 به سادگی توسط دیمون ارائه نمی شوند، بلکه از یک فایل گرفته شده اند. passwd. متغیر 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 در دبیان و اوبونتو

توسعه دهندگان دبیان و توزیع های مشتق شده را منتشر کرده اند نسخه بسیار اصلاح شده Vixie cron نسخه 3.0pl1. هیچ تفاوتی در نحو فایل های جدول وجود ندارد، برای کاربران همان Vixie cron است. بزرگترین ویژگی جدید: پشتیبانی syslog, SELinux را и PAM.

تغییرات کمتر قابل توجه، اما ملموس شامل مکان فایل های پیکربندی و جداول وظایف است.

جداول کاربر در دبیان در دایرکتوری /var/spool/cron/crontabs قرار دارند، جدول سیستم هنوز آنجاست - در /etc/crontab. جداول وظیفه مخصوص بسته دبیان در /etc/cron.d قرار می گیرند، جایی که شبح cron به طور خودکار آنها را می خواند. کنترل دسترسی کاربر توسط فایل های /etc/cron.allow و /etc/cron.deny کنترل می شود.

پوسته پیش‌فرض همچنان /bin/sh است که در دبیان یک پوسته کوچک سازگار با POSIX است. خط تیره، بدون خواندن هیچ گونه پیکربندی (در حالت غیر تعاملی) راه اندازی شد.

خود کرون در آخرین نسخه‌های دبیان از طریق systemd راه‌اندازی می‌شود و پیکربندی راه‌اندازی را می‌توان در /lib/systemd/system/cron.service مشاهده کرد. هیچ چیز خاصی در پیکربندی سرویس وجود ندارد؛ هر گونه مدیریت کار ظریف تری را می توان از طریق متغیرهای محیطی که مستقیماً در crontab هر کاربر اعلام شده انجام داد.

cronie در RedHat، Fedora و CentOS

کرونی - فورک Vixie cron نسخه 4.1. همانند دبیان، سینتکس تغییر نکرده است، اما پشتیبانی از PAM و SELinux، کار در یک کلاستر، ردیابی فایل ها با استفاده از inotify و سایر ویژگی ها اضافه شده است.

پیکربندی پیش‌فرض در مکان‌های معمول است: جدول سیستم در /etc/crontab است، بسته‌ها جداول خود را در /etc/cron.d قرار می‌دهند، جداول کاربر در /var/spool/cron/crontabs قرار می‌گیرند.

دیمون تحت کنترل systemd اجرا می شود، پیکربندی سرویس /lib/systemd/system/crond.service است.

در توزیع‌های Red Hat مانند، /bin/sh به‌طور پیش‌فرض در هنگام راه‌اندازی استفاده می‌شود که bash استاندارد است. لازم به ذکر است که هنگام اجرای cron job ها از طریق /bin/sh، پوسته bash در حالت سازگار با POSIX شروع می شود و هیچ پیکربندی اضافی را نمی خواند و در حالت غیر تعاملی اجرا می شود.

cronie در 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 Vixey خواندن لذت بخش است.

بنابراین، تصمیم گرفتم دستگاه cron را با استفاده از مثال برنامه cron مشترک در هر دو شاخه توسعه - Vixie cron 3.0pl1 تجزیه و تحلیل کنم. من مثال ها را با حذف ifdef هایی که خواندن را پیچیده می کنند و جزئیات جزئی را حذف می کنند، ساده می کنم.

کار شیطان را می توان به چند مرحله تقسیم کرد:

  1. مقداردهی اولیه برنامه
  2. جمع آوری و به روز رسانی لیست وظایف برای اجرا.
  3. حلقه cron اصلی در حال اجرا است.
  4. یک کار را شروع کنید.

بیایید به ترتیب به آنها نگاه کنیم.

مقداردهی اولیه

هنگام شروع، پس از بررسی آرگومان های فرآیند، cron کنترل کننده های سیگنال SIGCHLD و SIGHUP را نصب می کند. اولی یک ورودی گزارش در مورد خاتمه فرآیند فرزند ایجاد می کند، دومی توصیفگر فایل فایل log را می بندد:

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

سپس فرآیند "شریف‌سازی" می‌شود: با فراخوانی فورک و یک جلسه جدید در فرآیند فرزند (فرارخوانی setsid) یک کپی فرزند از فرآیند ایجاد می‌کند. فرآیند والد دیگر مورد نیاز نیست و خارج می شود:

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

خاتمه فرآیند والد، قفل فایل قفل را آزاد می کند. علاوه بر این، لازم است که PID موجود در فایل به کودک به روز شود. پس از این، پایگاه داده وظایف پر می شود:

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

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

سپس cron به چرخه اصلی کار می رود. اما قبل از آن، ارزش دارد نگاهی به بارگذاری لیست وظایف بیندازید.

جمع آوری و به روز رسانی لیست وظایف

تابع 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;
    }
}

در اینجا، یا متغیر محیطی با استفاده از توابع load_env / env_set تنظیم می‌شود (خطوط از فرم VAR=value) یا شرح کار با استفاده از تابع load_entry خوانده می‌شود (* * * * * /path/to/exec).

موجودیت ورودی که 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 یونیکس کاملاً ساده کار می کرد: پیکربندی را دوباره در یک حلقه بازخوانی کرد، وظایف دقیقه فعلی را به عنوان یک ابرکاربر راه اندازی کرد و تا شروع دقیقه بعد خوابید. این رویکرد ساده در ماشین‌های قدیمی‌تر به منابع زیادی نیاز داشت.

یک نسخه جایگزین در SysV پیشنهاد شد، که در آن دیمون یا تا نزدیکترین دقیقه ای که وظیفه تعریف شده بود یا برای 30 دقیقه به خواب رفت. منابع کمتری برای خواندن مجدد پیکربندی و بررسی وظایف در این حالت مصرف شد، اما به‌روزرسانی سریع فهرست کارها ناخوشایند شد.

Vixie cron به بررسی لیست وظایف هر دقیقه یک بار بازگشت، خوشبختانه در پایان دهه 80 منابع به میزان قابل توجهی در ماشین های استاندارد یونیکس وجود داشت:

/* первичная загрузка задач */
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 به سبک یونیکس خوب اجرا می شود، یعنی یک فورک برای انجام کار به صورت ناهمزمان انجام می دهد. فرآیند والد به راه اندازی وظایف ادامه می دهد، فرآیند فرزند فرآیند کار را آماده می کند:

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 است. من برخی از جزئیات جالب، به عنوان مثال، حسابداری برای کاربران از راه دور را حذف کردم، اما نکته اصلی را بیان کردم.

پس از کلمه

Cron یک برنامه شگفت آور ساده و مفید است که در بهترین سنت های دنیای یونیکس ساخته شده است. او هیچ کار اضافی انجام نمی دهد، اما چندین دهه است که کار خود را به طرز شگفت انگیزی انجام می دهد. دریافت کد نسخه ای که با اوبونتو ارائه می شود بیش از یک ساعت طول نکشید و من خیلی لذت بردم! امیدوارم توانسته باشم آن را با شما به اشتراک بگذارم.

شما را نمی‌دانم، اما کمی متاسفم که متوجه شدم برنامه‌نویسی مدرن، با گرایش به پیچیدگی بیش از حد و بیش از حد انتزاعی، برای مدت طولانی به چنین سادگی منجر نشده است.

جایگزین‌های مدرن زیادی برای cron وجود دارد: تایمرهای systemd به شما امکان می‌دهند سیستم‌های پیچیده با وابستگی‌ها را سازماندهی کنید، fcron به شما اجازه می‌دهد تا با انعطاف‌پذیری بیشتری مصرف منابع را بر اساس وظایف تنظیم کنید. اما شخصاً ساده ترین کرونتاب همیشه برای من کافی بود.

به طور خلاصه، عاشق یونیکس باشید، از برنامه های ساده استفاده کنید و فراموش نکنید که مانا را برای پلتفرم خود بخوانید!

منبع: www.habr.com

اضافه کردن نظر