Linuxda Cron: tarix, foydalanish va qurilma

Linuxda Cron: tarix, foydalanish va qurilma

Klassik baxtli soatlar tomosha qilmasligini yozgan. O'sha vahshiy paytlarda na dasturchilar, na Unix bo'lgan, ammo bugungi kunda dasturchilar aniq bilishadi: cron ularning o'rniga vaqtni kuzatib boradi.

Buyruqlar qatori yordamchi dasturlari men uchun ham zaiflik, ham mashaqqatdir. sed, awk, wc, cut va boshqa eski dasturlar har kuni serverlarimizdagi skriptlar tomonidan boshqariladi. Ularning aksariyati 70-yillardan boshlab rejalashtiruvchi cron uchun vazifalar sifatida yaratilgan.

Uzoq vaqt davomida men crondan yuzaki foydalanardim, tafsilotlarga kirmasdan, lekin bir kuni skriptni ishga tushirishda xatolikka duch kelganimda, uni yaxshilab o'rganishga qaror qildim. Ushbu maqola shunday paydo bo'ldi, uni yozish paytida men POSIX crontab, mashhur Linux distributivlaridagi asosiy cron variantlari va ularning ba'zilarining tuzilishi bilan tanishdim.

Siz Linuxdan foydalanasizmi va cron vazifalarini bajaryapsizmi? Unix tizimidagi ilovalar arxitekturasi sizni qiziqtiradimi? Keyin biz yo'ldamiz!

Mundarija

Turlarning kelib chiqishi

Foydalanuvchi yoki tizim dasturlarini davriy ravishda bajarish barcha operatsion tizimlarda aniq zaruratdir. Shu sababli, dasturchilar markazlashtirilgan tarzda vazifalarni rejalashtirish va bajarishga imkon beruvchi xizmatlarga bo'lgan ehtiyojni ancha oldin angladilar.

Unix-ga o'xshash operatsion tizimlar o'zlarining kelib chiqishini o'tgan asrning 7-yillarida Bell Labs-da, shu jumladan mashhur Ken Tompson tomonidan ishlab chiqilgan Unix-ning 70-versiyasiga borib taqaladi. Unix 7-versiyasida superfoydalanuvchi vazifalarini muntazam bajaruvchi cron xizmati ham mavjud.

Oddiy zamonaviy cron oddiy dasturdir, lekin asl versiyaning ishlash algoritmi yanada sodda edi: xizmat daqiqada bir marta uyg'ondi, bitta fayldan (/etc/lib/crontab) vazifalar bilan jadvalni o'qib chiqdi va dastur uchun bajarildi. hozirgi vaqtda bajarilishi kerak bo'lgan vazifalarni superuser.

Keyinchalik, oddiy va foydali xizmatning takomillashtirilgan versiyalari barcha Unix-ga o'xshash operatsion tizimlar bilan ta'minlandi.

Crontab formatining umumlashtirilgan tavsiflari va yordamchi dasturning asosiy printsiplari 1992 yilda Unix-ga o'xshash operatsion tizimlarning asosiy standarti - POSIXga kiritilgan va shu bilan de-fakto standartidan cron de-yure standartga aylandi.

1987 yilda Pol Viksi Unix foydalanuvchilarining cronga bo'lgan istaklari haqida so'rov o'tkazib, an'anaviy cronning ba'zi muammolarini tuzatuvchi va jadval fayllari sintaksisini kengaytiruvchi demonning yana bir versiyasini chiqardi.

Vixie cron-ning uchinchi versiyasida POSIX talablariga javob bera boshladi, bundan tashqari, dastur liberal litsenziyaga ega edi, aniqrog'i, README-dagi istaklardan tashqari, umuman litsenziya yo'q edi: muallif kafolat bermaydi, muallifning ismi. o'chirib bo'lmaydi va dastur faqat manba kodi bilan birga sotilishi mumkin. Ushbu talablar o'sha yillarda mashhur bo'lib borayotgan bepul dasturiy ta'minot tamoyillariga mos keldi, shuning uchun 90-yillarning boshlarida paydo bo'lgan ba'zi asosiy Linux distribyutorlari Vixie cronni o'z tizimi sifatida qabul qildi va bugungi kunda ham uni ishlab chiqmoqda.

Xususan, Red Hat va SUSE Vixie cron - cronie vilkasini ishlab chiqadi, Debian va Ubuntu esa Vixie cronning asl nashrini ko'plab yamoqlardan foydalanadi.

Keling, avval POSIX-da tasvirlangan crontab foydalanuvchi yordam dasturi bilan tanishamiz, shundan so'ng biz Vixie cron-da taqdim etilgan sintaksis kengaytmalarini va mashhur Linux distribyutorlarida Vixie cron o'zgarishlaridan foydalanishni ko'rib chiqamiz. Va nihoyat, pirojnoe ustidagi gilos - cron daemon qurilmasining tahlili.

POSIX crontab

Agar original cron har doim superuser uchun ishlagan bo'lsa, zamonaviy rejalashtiruvchilar ko'pincha oddiy foydalanuvchilarning vazifalari bilan shug'ullanadi, bu xavfsizroq va qulayroqdir.

Cronlar ikkita dastur to'plami sifatida taqdim etiladi: doimiy ishlaydigan cron demoni va foydalanuvchilar uchun mavjud crontab yordam dasturi. Ikkinchisi tizimdagi har bir foydalanuvchiga xos vazifalar jadvallarini tahrirlash imkonini beradi, demon esa foydalanuvchi va tizim jadvallaridan vazifalarni ishga tushiradi.

В POSIX standarti demonning xatti-harakati hech qanday tarzda tasvirlanmagan va faqat foydalanuvchi dasturi rasmiylashtirilgan crontab. Foydalanuvchi vazifalarini ishga tushirish mexanizmlarining mavjudligi, albatta, nazarda tutilgan, ammo batafsil tavsiflanmagan.

Crontab yordam dasturiga qo'ng'iroq qilib, siz to'rtta narsani qilishingiz mumkin: muharrirda foydalanuvchining vazifalar jadvalini tahrirlash, jadvalni fayldan yuklash, joriy vazifalar jadvalini ko'rsatish va vazifalar jadvalini tozalash. Crontab yordam dasturi qanday ishlashiga misollar:

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

Qo'ng'iroq qilganda crontab -e standart muhit o'zgaruvchisida ko'rsatilgan tahrirlovchidan foydalaniladi EDITOR.

Vazifalarning o'zi quyidagi formatda tavsiflanadi:

# строки-комментарии игнорируются
#
# задача, выполняемая ежеминутно
* * * * * /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

Yozuvlarning dastlabki beshta maydoni: daqiqalar [1..60], soatlar [0..23], oy kunlari [1..31], oylar [1..12], hafta kunlari [0. .6], bu erda 0 yakshanba. Oxirgi, oltinchi maydon standart buyruq tarjimoni tomonidan bajariladigan qatordir.

Birinchi beshta maydonda qiymatlarni vergul bilan ajratish mumkin:

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

Yoki defis bilan:

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

Foydalanuvchilarning vazifalarni rejalashtirishga kirishi POSIX da cron.allow va cron.deny fayllari bilan tartibga solinadi, ular mos ravishda crontab-ga kirish huquqiga ega foydalanuvchilar va dasturga kirish imkoni bo'lmagan foydalanuvchilar ro'yxatiga kiradi. Standart ushbu fayllarning joylashishini hech qanday tarzda tartibga solmaydi.

Standartga ko'ra, ishga tushirilgan dasturlarga kamida to'rtta muhit o'zgaruvchisi o'tkazilishi kerak:

  1. HOME - foydalanuvchining uy katalogi.
  2. LOGNAME - foydalanuvchi login.
  3. PATH - standart tizim yordam dasturlarini topishingiz mumkin bo'lgan yo'l.
  4. SHELL - foydalanilgan buyruq tarjimoniga yo'l.

Shunisi e'tiborga loyiqki, POSIX bu o'zgaruvchilar uchun qiymatlar qayerdan kelganligi haqida hech narsa aytmaydi.

Eng yaxshi sotuvchi - Vixie cron 3.0pl1

Mashhur cron variantlarining umumiy ajdodi Vixie cron 3.0pl1 bo'lib, 1992 yilda comp.sources.unix pochta ro'yxatiga kiritilgan. Biz ushbu versiyaning asosiy xususiyatlarini batafsil ko'rib chiqamiz.

Vixie cron ikkita dasturda (cron va crontab) mavjud. Odatdagidek, demon tizim vazifalari jadvali va individual foydalanuvchi topshiriq jadvallaridagi vazifalarni o‘qish va ishga tushirish uchun, crontab yordam dasturi esa foydalanuvchi jadvallarini tahrirlash uchun javobgardir.

Vazifalar jadvali va konfiguratsiya fayllari

Superuser vazifalari jadvali /etc/crontab da joylashgan. Tizim jadvalining sintaksisi Vixie cron sintaksisiga mos keladi, bundan mustasno, undagi oltinchi ustunda vazifa ishga tushirilgan foydalanuvchi nomi ko'rsatilgan:

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

Oddiy foydalanuvchi vazifalari jadvallari /var/cron/tabs/username-da joylashgan va bir xil sintaksisdan foydalanadi. Crontab yordam dasturini foydalanuvchi sifatida ishga tushirganingizda, bular tahrirlangan fayllardir.

Crontab-ga kirish huquqiga ega foydalanuvchilar ro'yxati /var/cron/allow va /var/cron/deny fayllarida boshqariladi, bunda foydalanuvchi nomini alohida qatorga kiritish kifoya.

Kengaytirilgan sintaksis

POSIX crontab bilan solishtirganda, Pol Vixeyning yechimi yordamchi dasturning vazifalar jadvallari sintaksisiga bir nechta juda foydali modifikatsiyalarni o'z ichiga oladi.

Jadvalning yangi sintaksisi mavjud bo'ldi: masalan, haftaning kunlarini yoki oylarini nom bilan belgilashingiz mumkin (dushanba, seshanba va boshqalar):

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

Vazifalarni ishga tushirish bosqichini belgilashingiz mumkin:

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

Bosqichlar va intervallarni aralashtirish mumkin:

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

Odatiy sintaksisning intuitiv alternativlari qo'llab-quvvatlanadi (qayta yuklash, yillik, yillik, oylik, haftalik, har kuni, yarim tunda, soatlik):

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

Vazifani bajarish muhiti

Vixie cron sizga ishlaydigan ilovalar muhitini o'zgartirish imkonini beradi.

USER, LOGNAME va HOME muhit oʻzgaruvchilari oddiy demon tomonidan taqdim etilmaydi, balki fayldan olingan. passwd. PATH o'zgaruvchisi "/usr/bin:/bin" ga, SHELL o'zgaruvchisi esa "/bin/sh" ga o'rnatiladi. LOGNAMEdan tashqari barcha oʻzgaruvchilarning qiymatlari foydalanuvchi jadvallarida oʻzgartirilishi mumkin.

Ba'zi muhit o'zgaruvchilari (asosan SHELL va HOME) vazifani bajarish uchun cron tomonidan qo'llaniladi. Shaxsiy vazifalarni bajarish uchun standart sh o'rniga bash dan foydalanish quyidagicha ko'rinishi mumkin:

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

Oxir oqibat, jadvalda aniqlangan barcha muhit o'zgaruvchilari (cron tomonidan foydalaniladi yoki jarayon tomonidan kerak) ishlaydigan vazifaga o'tadi.

Fayllarni tahrirlash uchun crontab VISUAL yoki EDITOR muhit o'zgaruvchisida ko'rsatilgan muharrirdan foydalanadi. Agar crontab ishga tushirilgan muhitda ushbu o'zgaruvchilar aniqlanmagan bo'lsa, u holda "/usr/ucb/vi" ishlatiladi (ucb Kaliforniya universiteti, Berkli bo'lishi mumkin).

Debian va Ubuntu-da cron

Debian va lotin distributivlarini ishlab chiquvchilar chiqarildi juda o'zgartirilgan versiya Vixie cron versiyasi 3.0pl1. Jadval fayllari sintaksisida hech qanday farq yo'q, foydalanuvchilar uchun bu bir xil Vixie cron. Eng katta yangi xususiyat: qo'llab-quvvatlash syslog, SELinux и WFP.

Kamroq sezilarli, ammo sezilarli o'zgarishlar konfiguratsiya fayllari va vazifalar jadvallarining joylashuvini o'z ichiga oladi.

Debian'dagi foydalanuvchi jadvallari /var/spool/cron/crontabs katalogida joylashgan, tizim jadvali hali ham mavjud - /etc/crontab ichida. Debian paketiga oid vazifalar jadvallari /etc/cron.d ichiga joylashtirilgan, u yerdan cron demoni ularni avtomatik ravishda o'qiydi. Foydalanuvchiga kirishni boshqarish /etc/cron.allow va /etc/cron.deny fayllari tomonidan boshqariladi.

Odatiy qobiq hali ham /bin/sh bo'lib, Debian-da POSIX-ga mos keladigan kichik qobiqdir. Chiziq, hech qanday konfiguratsiyani o'qimasdan ishga tushirildi (interaktiv bo'lmagan rejimda).

Debianning so'nggi versiyalarida Cronning o'zi systemd orqali ishga tushiriladi va ishga tushirish konfiguratsiyasini /lib/systemd/system/cron.service da ko'rish mumkin. Xizmat konfiguratsiyasida hech qanday maxsus narsa yo'q; har qanday nozik vazifani boshqarish har bir foydalanuvchining crontab'ida to'g'ridan-to'g'ri e'lon qilingan muhit o'zgaruvchilari orqali amalga oshirilishi mumkin.

RedHat, Fedora va CentOS-da cronie

kroni - Vixie cron 4.1 versiyasining vilkalari. Debian-da bo'lgani kabi, sintaksis o'zgarmadi, lekin PAM va SELinux-ni qo'llab-quvvatlash, klasterda ishlash, inotify yordamida fayllarni kuzatish va boshqa funktsiyalar qo'shildi.

Odatiy konfiguratsiya odatiy joylarda: tizim jadvali /etc/crontab da, paketlar o'z jadvallarini /etc/cron.d da, foydalanuvchi jadvallari /var/spool/cron/crontabs da joylashgan.

Demon tizim nazorati ostida ishlaydi, xizmat konfiguratsiyasi - /lib/systemd/system/crond.service.

Red Hat-ga o'xshash tarqatishlarda, /bin/sh sukut bo'yicha ishga tushirishda ishlatiladi, bu standart bash hisoblanadi. Shuni ta'kidlash kerakki, /bin/sh orqali cron ishlarini bajarayotganda, bash qobig'i POSIX-mos rejimda boshlanadi va interaktiv bo'lmagan rejimda ishlaydigan hech qanday qo'shimcha konfiguratsiyani o'qimaydi.

SLES va openSUSE-da cronie

Nemis tarqatish SLES va uning hosilasi openSUSE bir xil cronie-dan foydalanadi. Bu erda demon systemd ostida ham ishga tushiriladi, xizmat konfiguratsiyasi /usr/lib/systemd/system/cron.service da joylashgan. Konfiguratsiya: /etc/crontab, /etc/cron.d, /var/spool/cron/tabs. /bin/sh - bu POSIX-mos bo'lmagan interaktiv rejimda ishlaydigan bir xil bash.

Vixie cron qurilmasi

Cronning zamonaviy avlodlari Vixie cron bilan solishtirganda tubdan o'zgarmadi, lekin hali ham dastur tamoyillarini tushunish uchun talab qilinmaydigan yangi xususiyatlarga ega bo'ldi. Ushbu kengaytmalarning aksariyati yomon ishlab chiqilgan va kodni chalkashtirib yuboradi. Pol Vixey tomonidan yaratilgan asl cron manba kodini o'qish juda yoqimli.

Shuning uchun men cron qurilmasini rivojlanishning ikkala tarmog'i uchun umumiy bo'lgan cron dasturi misolidan foydalanib tahlil qilishga qaror qildim - Vixie cron 3.0pl1. Men o'qishni qiyinlashtiradigan ifdeflarni olib tashlash va kichik tafsilotlarni o'tkazib yuborish orqali misollarni soddalashtiraman.

Jinning ishi bir necha bosqichlarga bo'linishi mumkin:

  1. Dasturni ishga tushirish.
  2. Bajarilishi kerak bo'lgan vazifalar ro'yxatini to'plash va yangilash.
  3. Asosiy cron tsikli ishlaydi.
  4. Vazifani boshlang.

Keling, ularni tartibda ko'rib chiqaylik.

Boshlash

Ishga tushganda, jarayon argumentlarini tekshirgandan so'ng, cron SIGCHLD va SIGHUP signal ishlov beruvchilarini o'rnatadi. Birinchisi, bola jarayonining tugashi haqida jurnalga yozuv kiritadi, ikkinchisi jurnal faylining fayl deskriptorini yopadi:

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

Cron demoni har doim tizimda yolg'iz ishlaydi, faqat superuser sifatida va asosiy cron katalogidan. Quyidagi qo'ng'iroqlar demon jarayonining PID-kodi bilan blokirovka faylini yaratadi, foydalanuvchi to'g'ri ekanligiga ishonch hosil qiling va joriy katalogni asosiysiga o'zgartiring:

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

Jarayonlarni boshlashda ishlatiladigan standart yo'l o'rnatiladi:

setenv("PATH", _PATH_DEFPATH, 1);

Keyin jarayon "daemonizatsiya qilinadi": u forkni chaqirish va bola jarayonida yangi sessiya (setsid chaqiruvi) orqali jarayonning bola nusxasini yaratadi. Ota-ona jarayoni endi kerak emas va u chiqadi:

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

Ota-ona jarayonining tugatilishi qulflash faylidagi qulfni chiqaradi. Bundan tashqari, fayldagi PID-ni bolaga yangilash talab qilinadi. Shundan so'ng, vazifa ma'lumotlar bazasi to'ldiriladi:

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

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

Keyin cron asosiy ish aylanishiga o'tadi. Ammo bundan oldin, vazifalar ro'yxatini yuklashni ko'rib chiqishga arziydi.

Vazifalar ro'yxatini to'plash va yangilash

load_ma'lumotlar bazasi funksiyasi vazifalar ro'yxatini yuklash uchun javobgardir. U asosiy tizim crontab va foydalanuvchi fayllari bilan katalogni tekshiradi. Agar fayllar va katalog o'zgarmagan bo'lsa, vazifalar ro'yxati qayta o'qilmaydi. Aks holda, vazifalarning yangi ro'yxati shakllana boshlaydi.

Maxsus fayl va jadval nomlari bilan tizim faylini yuklash:

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

Foydalanuvchi jadvallarini tsiklda yuklash:

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

Shundan so'ng, eski ma'lumotlar bazasi yangisi bilan almashtiriladi.

Yuqoridagi misollarda process_crontab funksiya chaqiruvi jadval fayl nomiga mos keladigan foydalanuvchi mavjudligini tekshiradi (agar u superuser bo'lmasa) va keyin load_user ni chaqiradi. Ikkinchisi allaqachon faylni satr satr o'qiydi:

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

Bu yerda yo muhit oʻzgaruvchisi load_env / env_set funksiyalari yordamida oʻrnatiladi (VAR=qiymat shaklidagi satrlar) yoki load_entry funksiyasi yordamida vazifa tavsifi oʻqiladi (* * * * * /path/to/exec).

load_entry qaytaradigan kirish ob'ekti bizning vazifamiz bo'lib, u umumiy vazifalar ro'yxatiga joylashtirilgan. Funktsiyaning o'zi vaqt formatini batafsil tahlil qiladi, ammo biz atrof-muhit o'zgaruvchilari va vazifalarni ishga tushirish parametrlarini shakllantirishga ko'proq qiziqamiz:

/* пользователь и группа для запуска задачи берутся из 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);

Asosiy halqa joriy vazifalar ro'yxati bilan ishlaydi.

Asosiy tsikl

Unix-ning 7-versiyasidagi asl cron juda oddiy ishladi: u konfiguratsiyani tsiklda qayta o'qib chiqdi, superuser sifatida joriy daqiqaning vazifalarini ishga tushirdi va keyingi daqiqa boshlanishigacha uxladi. Eski mashinalarda bunday oddiy yondashuv juda ko'p resurslarni talab qildi.

SysV-da muqobil versiya taklif qilindi, unda demon vazifa aniqlangan eng yaqin daqiqagacha yoki 30 daqiqa davomida uxlab qoldi. Ushbu rejimda konfiguratsiyani qayta o'qish va vazifalarni tekshirish uchun kamroq resurslar sarflandi, ammo vazifalar ro'yxatini tezda yangilash noqulay bo'ldi.

Vixie cron daqiqada bir marta vazifalar ro'yxatini tekshirishga qaytdi, xayriyatki, 80-yillarning oxiriga kelib, standart Unix mashinalarida sezilarli darajada ko'proq resurslar mavjud edi:

/* первичная загрузка задач */
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 funksiyasi vazifalarni bajarishda bevosita ishtirok etadi, job_runqueue (vazifalarni sanash va ishga tushirish) va do_command (har bir alohida topshiriqni bajarish) funksiyalarini chaqiradi. Oxirgi funktsiyani batafsilroq ko'rib chiqishga arziydi.

Vazifani bajarish

do_command funktsiyasi yaxshi Unix uslubida bajariladi, ya'ni vazifani asinxron tarzda bajarish uchun vilkalar qiladi. Ota-ona jarayoni vazifalarni ishga tushirishda davom etadi, bola jarayoni esa vazifa jarayonini tayyorlaydi:

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

Child_process-da juda ko'p mantiq mavjud: u standart chiqish va xato oqimlarini o'ziga oladi, keyin uni pochtaga jo'natadi (agar MAILTO muhit o'zgaruvchisi topshiriqlar jadvalida ko'rsatilgan bo'lsa) va nihoyat, asosiyni kutadi. vazifani bajarish jarayoni.

Vazifa jarayoni boshqa vilka tomonidan shakllantiriladi:

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

Bu, asosan, barcha cron. Men ba'zi qiziqarli tafsilotlarni o'tkazib yubordim, masalan, masofaviy foydalanuvchilarni hisobga olish, lekin men asosiy narsani aytib berdim.

So'zdan keyin

Cron hayratlanarli darajada sodda va foydali dastur bo'lib, Unix dunyosining eng yaxshi an'analarida yaratilgan. U qo'shimcha hech narsa qilmaydi, lekin u bir necha o'n yillar davomida o'z ishini ajoyib tarzda bajarmoqda. Ubuntu bilan birga kelgan versiya uchun kodni o'rganish bir soatdan ko'proq vaqtni oldi va men juda xursand bo'ldim! Umid qilamanki, men buni siz bilan baham ko'ra oldim.

Siz haqingizda bilmayman, lekin zamonaviy dasturlash o'zining haddan tashqari murakkab va mavhumlikka moyilligi bilan uzoq vaqt davomida bunday soddalikka yordam bermaganini tushunib, biroz xafa bo'ldim.

Cron-ga ko'plab zamonaviy muqobillar mavjud: systemd-taymerlar sizga bog'liqliklar bilan murakkab tizimlarni tashkil qilish imkonini beradi, fcron vazifalar bo'yicha resurslar sarfini yanada moslashuvchan tartibga solish imkonini beradi. Lekin shaxsan men uchun eng oddiy crontab har doim etarli edi.

Muxtasar qilib aytganda, Unix-ni seving, oddiy dasturlardan foydalaning va platformangiz uchun mana o'qishni unutmang!

Manba: www.habr.com

a Izoh qo'shish