Linux-da Cron: tarix, istifadə və cihaz

Linux-da Cron: tarix, istifadə və cihaz

Klassik yazırdı ki, xoşbəxt saatlar müşahidə olunmur. O vəhşi dövrlərdə hələ proqramçılar və ya Unix yox idi, lakin bu günlərdə proqramçılar dəqiq bilirlər: onların əvəzinə cron vaxtı izləyəcək.

Komanda xətti utilitləri mənim üçün həm zəiflik, həm də rutindir. sed, awk, wc, cut və digər köhnə proqramlar hər gün serverlərimizdə skriptlər tərəfindən idarə olunur. Onların bir çoxu 70-ci illərdən bir planlaşdırıcı olan cron üçün tapşırıqlar kimi hazırlanmışdır.

Mən uzun müddət təfərrüatlara varmadan crondan səthi istifadə etdim, lakin bir gün skripti işləyərkən xəta ilə üzləşdim və onu hərtərəfli araşdırmaq qərarına gəldim. POSIX crontab, məşhur Linux paylamalarında əsas cron variantları və onlardan bəzilərinin dizaynı ilə tanış olduğum bu məqalə belə yarandı.

Linux istifadə edirsiniz və cron-da tapşırıqlar icra edirsiniz? Unix-də sistem proqramlarının arxitekturası ilə maraqlanırsınız? Onda biz yolumuza davam edirik!

Məzmun

Növlərin mənşəyi

İstifadəçi və ya sistem proqramlarının vaxtaşırı icrası bütün əməliyyat sistemlərində aşkar zərurətdir. Buna görə də, proqramçılar çox uzun müddət mərkəzləşdirilmiş planlaşdırma və tapşırıqların icrasına imkan verən xidmətlərə ehtiyac olduğunu qəbul etdilər.

Unix-ə bənzər əməliyyat sistemləri öz nəsillərini keçən əsrin 7-ci illərində Bell Labs-da, o cümlədən məşhur Ken Thompson-da hazırlanmış Unix Version 70-ə qədər izləyir. Versiya 7 Unix həmçinin superuser tapşırıqlarının müntəzəm icrası üçün xidmət olan cron ilə göndərilir.

Tipik müasir cron sadə proqramdır, lakin orijinal versiyanın alqoritmi daha sadə idi: xidmət dəqiqədə bir dəfə oyandı, bir fayldan (/etc/lib/crontab) tapşırıqları olan cədvəli oxudu və super istifadəçi üçün yerinə yetirildi. cari dəqiqədə tamamlanmalı olan tapşırıqlar.

Sonradan, sadə və faydalı xidmətin təkmilləşdirilmiş versiyaları bütün Unix-ə bənzər əməliyyat sistemləri ilə göndərildi.

1992-ci ildə crontab formatının ümumiləşdirilmiş təsvirləri və yardım proqramının əsas prinsipləri Unix-ə bənzər əməliyyat sistemləri üçün əsas standarta - POSIX-ə daxil edildi və beləliklə de-fakto standartdan cron de-yure standart oldu.

1987-ci ildə Paul Vixie, Unix istifadəçiləri arasında cron istəkləri haqqında sorğu keçirdikdən sonra, ənənəvi cronun bəzi problemlərini həll edən və cədvəl fayllarının sintaksisini genişləndirən demonun başqa bir versiyasını buraxdı.

Vixie cron-un üçüncü versiyası POSIX tələblərinə cavab verməyə başladı, əlavə olaraq proqramın liberal lisenziyası var idi, daha doğrusu, README-dəki istəklər istisna olmaqla, ümumiyyətlə lisenziya yox idi: müəllif zəmanət vermir, müəllifin adı silinə bilməz və proqram yalnız mənbə kodu ilə birlikdə satıla bilər. Bu tələblər o illərdə populyarlıq qazanan pulsuz proqram təminatının prinsiplərinə uyğun olduğu ortaya çıxdı, buna görə də 90-cı illərin əvvəllərində ortaya çıxan bəzi əsas Linux paylamaları Vixie cron-u sistem kimi götürdü və hələ də inkişaf etdirir.

Xüsusilə, Red Hat və SUSE Vixie cron - cronie çəngəlini inkişaf etdirir, Debian və Ubuntu isə çoxlu yamaqlarla orijinal Vixie cron nəşrindən istifadə edir.

Gəlin əvvəlcə POSIX istifadəçi tərəfindən təyin olunan crontab yardım proqramına baxaq, sonra Vixie cron-da təqdim edilən sintaksis genişlənmələrinə və məşhur Linux paylamalarında Vixie cron variasiyalarının istifadəsinə baxaq. Və nəhayət, tortun üzərindəki buzlanma cron demonunun cihazını sökməkdir.

POSIX crontab

Orijinal cron həmişə super istifadəçi üçün işləsə də, müasir planlaşdırıcılar daha təhlükəsiz və daha rahat olan müntəzəm istifadəçi tapşırıqları ilə məşğul olurlar.

Crons iki proqram dəsti ilə gəlir: daimi işləyən cron demonu və istifadəçinin əlçatan olduğu crontab yardım proqramı. Sonuncu sistemdəki hər bir istifadəçi üçün xüsusi tapşırıq cədvəllərini redaktə etməyə imkan verir, daemon isə istifadəçi və sistem cədvəllərindən tapşırıqları yerinə yetirir.

В POSIX standartı demonun davranışı heç bir şəkildə təsvir olunmur və yalnız istifadəçi proqramı rəsmiləşdirilir crontab. İstifadəçi tapşırıqlarını işə salmaq üçün mexanizmlərin mövcudluğu, əlbəttə ki, nəzərdə tutulur, lakin ətraflı təsvir edilmir.

Crontab yardım proqramını çağırmaqla dörd şey etmək olar: istifadəçinin tapşırıq cədvəlini redaktorda redaktə etmək, cədvəli fayldan yükləmək, cari tapşırıq cədvəlini göstərmək və tapşırıq cədvəlini təmizləmək. Crontab yardım proqramının nümunələri:

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

Zəng edəndə crontab -e standart mühit dəyişənində göstərilən redaktordan istifadə ediləcək EDITOR.

Tapşırıqların özləri aşağıdakı formatda təsvir edilmişdir:

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

İlk beş qeyd sahəsi: dəqiqələr [1..60], saatlar [0..23], ayın günləri [1..31], aylar [1..12], həftənin günləri [0.. 6], burada 0 — bazar günü. Sonuncu, altıncı sahə standart əmr tərcüməçisi tərəfindən yerinə yetiriləcək bir xəttdir.

İlk beş sahədə dəyərlər vergüllə ayrıla bilər:

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

Və ya defislə:

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

Tapşırıqların planlaşdırılmasına istifadəçi girişi POSIX-də cron.allow və cron.deny faylları ilə tənzimlənir, bunlar müvafiq olaraq crontab girişi olan istifadəçiləri və proqrama girişi olmayan istifadəçiləri sadalayır. Standart bu faylların yerini heç bir şəkildə tənzimləmir.

Başlanmış proqramlar, standarta uyğun olaraq, ən azı dörd mühit dəyişənindən keçməlidir:

  1. HOME istifadəçinin ev kataloqudur.
  2. LOGNAME - istifadəçi girişi.
  3. PATH - standart sistem yardımçılarını tapa biləcəyiniz yol.
  4. SHELL istifadə olunan qabığa gedən yoldur.

Qeyd edək ki, POSIX bu dəyişənlər üçün dəyərlərin haradan gəldiyi barədə heç nə demir.

Bestseller - Vixie cron 3.0pl1

Məşhur cron variantlarının ortaq əcdadı 3.0-ci ildə comp.sources.unix poçt siyahısında təqdim edilmiş Vixie cron 1pl1992-dir. Bu versiyanın əsas xüsusiyyətlərini daha ətraflı nəzərdən keçirəcəyik.

Vixie cron iki proqramda gəlir (cron və crontab). Həmişə olduğu kimi, daemon sistem tapşırıqları cədvəlindən və fərdi istifadəçi tapşırıq cədvəllərindən tapşırıqların oxunması və icrasına cavabdehdir, crontab yardım proqramı isə istifadəçi cədvəllərinin redaktəsinə cavabdehdir.

Tapşırıq cədvəli və konfiqurasiya faylları

Superuser tapşırıq cədvəli /etc/crontab-da yerləşir. Sistem cədvəlinin sintaksisi Vixie cron sintaksisinə uyğundur, istisna olmaqla, altıncı sütunda tapşırığın işə salındığı istifadəçinin adı göstərilir:

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

Daimi istifadəçi tapşırıq cədvəlləri /var/cron/tabs/username-də yerləşir və ümumi sintaksisdən istifadə edir. Siz crontab yardım proqramını istifadəçi kimi işlətdiyiniz zaman redaktə edilən bu fayllardır.

Crontab-a girişi olan istifadəçilərin siyahıları /var/cron/allow və /var/cron/deny fayllarında idarə olunur, burada istifadəçi adını ayrıca sətirə daxil etmək kifayətdir.

Genişləndirilmiş Sintaksis

POSIX crontab ilə müqayisədə, Paul Wixey-nin həlli yardım proqramının tapşırıq cədvəllərinin sintaksisində çox faydalı dəyişiklikləri ehtiva edir.

Yeni cədvəl sintaksisi əlçatan oldu: məsələn, həftənin günlərini və ya aylarını adla təyin edə bilərsiniz (Bazar ertəsi, Çərşənbə axşamı və s.):

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

Tapşırıqların işə salındığı addımı təyin edə bilərsiniz:

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

Addımlar və intervallar qarışdırıla bilər:

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

Adi sintaksisə intuitiv alternativlər dəstəklənir (yenidən yükləmə, illik, illik, aylıq, həftəlik, gündəlik, gecə yarısı, saatlıq):

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

Tapşırıqların icrası mühiti

Vixie cron işə salınan proqramların mühitini dəyişməyə imkan verir.

USER, LOGNAME və HOME mühit dəyişənləri yalnız demon tərəfindən təmin edilmir, həm də fayldan götürülür. passwd. PATH dəyişəni "/usr/bin:/bin", SHELL dəyişəni isə "/bin/sh" olaraq təyin edilib. LOGNAME istisna olmaqla, bütün dəyişənlərin dəyərləri istifadəçi cədvəllərində dəyişdirilə bilər.

Bəzi mühit dəyişənləri (əsasən SHELL və HOME) bir tapşırığa başlamaq üçün cron tərəfindən istifadə olunur. İstifadəçi tapşırıqlarını yerinə yetirmək üçün standart sh əvəzinə bash istifadə etmək belə görünə bilər:

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

Nəhayət, cədvəldə müəyyən edilmiş bütün mühit dəyişənləri (ya cron tərəfindən istifadə olunur, ya da proses tərəfindən tələb olunur) çalışan tapşırığa ötürüləcək.

Faylları redaktə etmək üçün crontab VISUAL və ya REDAKTOR mühit dəyişənində göstərilən redaktordan istifadə edir. Əgər crontab-ın işlədildiyi mühitdə bu dəyişənlər müəyyən edilməyibsə, o zaman "/usr/ucb/vi" istifadə olunur (ucb, ehtimal ki, Berkli Kaliforniya Universitetidir).

Debian və Ubuntu-da cron

Debian və törəmələri tərtibatçıları buraxdılar ciddi şəkildə dəyişdirilmiş versiya Vixie cron 3.0pl1 versiyası. Cədvəl fayllarının sintaksisində heç bir fərq yoxdur, istifadəçilər üçün bu eyni Vixie crondur. Ən Böyük Yeni Xüsusiyyətlər: Dəstək syslog, SELinux и PAM.

Daha az nəzərə çarpan, lakin nəzərəçarpacaq dəyişikliklərdən - konfiqurasiya fayllarının və tapşırıq cədvəllərinin yeri.

Debian-da istifadəçi cədvəlləri /var/spool/cron/crontabs kataloqunda yerləşir, sistem cədvəli hələ də oradadır - /etc/crontab. Debian paketinə aid tapşırıq cədvəlləri /etc/cron.d-də yerləşdirilir, cron demon onları avtomatik oxuyur. İstifadəçi girişinə nəzarət /etc/cron.allow və /etc/cron.deny faylları ilə idarə olunur.

Defolt qabıq hələ də /bin/sh-dir, Debian-da kiçik POSIX-ə uyğun qabıqdır. tire, heç bir konfiqurasiyanı oxumadan işə salındı ​​(interaktiv olmayan rejimdə).

Debian-ın son versiyalarında Cron özü systemd vasitəsilə idarə olunur və başlanğıc konfiqurasiyası /lib/systemd/system/cron.service-də tapıla bilər. Xidmət konfiqurasiyasında xüsusi bir şey yoxdur, hər hansı daha incə tapşırığın idarə edilməsi birbaşa hər bir istifadəçinin crontabında elan edilmiş mühit dəyişənləri vasitəsilə edilə bilər.

RedHat, Fedora və CentOS-da cronie

kroni - Vixie cron versiyası 4.1. Debian-da olduğu kimi, sintaksis dəyişməyib, lakin PAM və SELinux üçün dəstək, klasterdə işləmə, inotify ilə faylların monitorinqi və digər funksiyalar əlavə edildi.

Standart konfiqurasiya adi yerlərdədir: sistem cədvəli /etc/crontab-da, paketlər öz cədvəllərini /etc/cron.d-də yerləşdirir, istifadəçi cədvəlləri /var/spool/cron/crontabs-a keçir.

Demon systemd altında işləyir, xidmət konfiqurasiyası /lib/systemd/system/crond.service-dir.

Red Hat kimi paylamalarda standart başlanğıc standart bash olan /bin/sh-dir. Qeyd edək ki, /bin/sh vasitəsilə cron işlərini yerinə yetirərkən, bash qabığı POSIX-ə uyğun rejimdə başlayır və qeyri-interaktiv rejimdə işləyən heç bir əlavə konfiqurasiyanı oxumur.

SLES və openSUSE-də cronie

Alman SLES paylanması və onun openSUSE törəməsi eyni cronie-dən istifadə edir. Burada daemon da systemd altında işləyir, xidmət konfiqurasiyası /usr/lib/systemd/system/cron.service daxilindədir. Konfiqurasiya: /etc/crontab, /etc/cron.d, /var/spool/cron/tabs. /bin/sh POSIX uyğun qeyri-interaktiv rejimdə işləyən eyni bashdır.

Vixie cron cihazı

Cronun müasir nəsilləri Vixie cron ilə müqayisədə köklü şəkildə dəyişməyib, lakin hələ də proqramın prinsiplərini başa düşmək üçün tələb olunmayan yeni xüsusiyyətlər əldə ediblər. Bu uzantıların çoxu səliqəsizdir və kodu qarışdırır. Paul Wixie tərəfindən orijinal cron mənbə kodu oxumaqdan zövq alır.

Buna görə də, cron inkişafının hər iki filialı üçün ümumi olan bir proqram nümunəsindən istifadə edərək cron cihazını təhlil etmək qərarına gəldim - Vixie cron 3.0pl1. Oxumağı çətinləşdirən ifdefləri silməklə və ikinci dərəcəli detalları buraxmaqla misalları sadələşdirəcəyəm.

Cinin işi bir neçə mərhələyə bölünə bilər:

  1. Proqramın işə salınması.
  2. İcra ediləcək tapşırıqların siyahısını toplayın və yeniləyin.
  3. Əsas cron döngəsinin işi.
  4. Tapşırığa başlamaq.

Gəlin onları sıra ilə götürək.

Başlanğıc

Başlanğıcda, proses arqumentlərini yoxladıqdan sonra cron SIGCHLD və SIGHUP siqnal işləyicilərini quraşdırır. Birincisi uşaq prosesinin dayandırılması ilə bağlı qeydi qeyd edir, ikincisi isə log faylının fayl deskriptorunu bağlayır:

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

Sistemdəki cron demonu həmişə təkbaşına işləyir, yalnız super istifadəçi rolunda və əsas cron kataloqundan. Aşağıdakı zənglər daemon prosesinin PID-si ilə kilid faylı yaradır, istifadəçinin düzgün olduğundan əmin olun və cari kataloqu əsas qovluğa dəyişdirin:

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

Prosesləri başlatarkən istifadə ediləcək standart yol təyin edilmişdir:

setenv("PATH", _PATH_DEFPATH, 1);

Sonra, proses “daemonizasiya olunur”: o, fork çağırmaqla prosesin uşaq nüsxəsini və uşaq prosesində yeni sessiyanı (setsid çağırmaqla) yaradır. Ana prosesə artıq ehtiyac yoxdur - və o, çıxır:

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

Ana prosesin dayandırılması kilid faylındakı kilidi buraxır. Bundan əlavə, fayldakı PID-i uşaq üçün yeniləməlisiniz. Bundan sonra tapşırıqlar bazası doldurulur:

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

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

Sonra cron əsas iş döngəsinə keçir. Ancaq bundan əvvəl tapşırıq siyahısını yükləməyə nəzər salmağa dəyər.

Tapşırıqlar siyahısının toplanması və yenilənməsi

load_database funksiyası tapşırıqlar siyahısının yüklənməsinə cavabdehdir. Əsas sistem crontabını və istifadəçi faylları kataloqunu yoxlayır. Fayllar və qovluq dəyişməyibsə, tapşırıqların siyahısı yenidən oxunmur. Əks halda, tapşırıqların yeni siyahısı formalaşmağa başlayır.

Xüsusi fayl və cədvəl adları olan sistem faylının yüklənməsi:

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

Döngüdə fərdi cədvəllərin yüklənməsi:

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

Bundan sonra köhnə verilənlər bazası yenisi ilə əvəz olunur.

Yuxarıdakı nümunələrdə process_crontab-a edilən zəng cədvəlin fayl adına uyğun istifadəçinin mövcudluğunu yoxlayır (əgər bu superuser deyilsə) və sonra load_user-i çağırır. Sonuncu artıq faylın özünü sətir-sətir oxuyur:

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

Burada ya mühit dəyişəni load_env / env_set funksiyaları tərəfindən təyin edilir (VAR=dəyər kimi sətirlər), ya da tapşırıq təsviri (* * * * * /path/to/exec) load_entry funksiyası tərəfindən oxunur.

load_entry-nin qaytardığı giriş obyekti ümumi tapşırıqlar siyahısında yerləşdirilən vəzifəmizdir. Funksiyanın özündə vaxt formatının ətraflı təhlili aparılır, lakin bizi daha çox mühit dəyişənlərinin və tapşırıqların işə salınma parametrlərinin formalaşması maraqlandırır:

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

Tapşırıqların faktiki siyahısı ilə əsas döngə işləyir.

Əsas Döngü

Version 7 Unix-dən olan orijinal cron olduqca sadə işləyirdi: o, konfiqurasiyanı döngədə yenidən oxudu, cari dəqiqənin tapşırıqlarını super istifadəçi kimi başladı və növbəti dəqiqənin əvvəlinə qədər yatdı. Köhnə maşınlarda bu sadə yanaşma çoxlu resurs tələb edirdi.

SysV-də, demonun ya tapşırığın müəyyən edildiyi ən yaxın dəqiqəyə qədər, ya da 30 dəqiqə yatdığı alternativ versiya təklif edilmişdir. Bu rejimdə konfiqurasiyanı yenidən oxumaq və tapşırıqları yoxlamaq üçün resurslar daha az istehlak edildi, lakin tapşırıqların siyahısını tez yeniləmək əlverişsiz oldu.

Vixie cron dəqiqədə bir dəfə tapşırıq siyahılarını yoxlamağa qayıtdı, çünki 80-ci illərin sonunda standart Unix maşınlarında daha çox resurs var idi:

/* первичная загрузка задач */
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 funksiyası birbaşa tapşırıqların icrasında iştirak edir, job_runqueue (tapşırıqları sadalamaq və başlamaq) və do_command (hər bir fərdi tapşırığa başlamaq) funksiyalarını çağırır. Son funksiyanı daha ətraflı təhlil etməyə dəyər.

Tapşırığa başlamaq

do_command funksiyası yaxşı Unix üslubunda yerinə yetirilir, yəni bir tapşırığı asinxron şəkildə yerinə yetirmək üçün çəngəl edir. Ana proses tapşırıqları yerinə yetirməyə davam edir, uşaq prosesi isə tapşırıq prosesini hazırlayır:

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

Uşaq_prosesində çoxlu məntiq var: o, standart çıxışı və xəta axınlarını öz üzərinə götürür ki, o, daha sonra poçta göndərilə bilsin (əgər MAILTO mühit dəyişəni tapşırıq cədvəlində göstərilibsə) və nəhayət, o, gözləyir. tapşırığın əsas prosesini tamamlamaq üçün.

Tapşırıq prosesi başqa bir çəngəl ilə formalaşır:

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, ümumiyyətlə, bütün crondur. Bəzi maraqlı detalları, məsələn, uzaq istifadəçilər üçün uçotu buraxdım, amma əsas şeyi qeyd etdim.

Sözündən sonra

Cron, Unix dünyasının ən yaxşı ənənələrində hazırlanmış təəccüblü dərəcədə sadə və faydalı proqramdır. O, əlavə heç nə etmir, lakin artıq bir neçə onilliklərdir ki, öz işini əla görür. Ubuntu ilə göndərilən versiyanın kodunu nəzərdən keçirmək bir saatdan az vaxt apardı və mən çox əyləndim! Ümid edirəm sizinlə paylaşa bildim.

Sizi bilmirəm, amma bir az kədərləndim ki, müasir proqramlaşdırma özünün həddən artıq mürəkkəbləşdirməyə və həddən artıq mücərrədliyə meyli ilə çoxdan belə sadəliyə yardımçı olmaqdan çıxıb.

Cron-a bir çox müasir alternativlər var: systemd-taymerləri asılılıqları olan mürəkkəb sistemləri təşkil etməyə imkan verir, fcronda siz tapşırıqların resurs istehlakını daha çevik şəkildə tənzimləyə bilərsiniz. Amma şəxsən mənim üçün ən sadə crontab həmişə kifayət olub.

Bir sözlə, Unix-i sevin, sadə proqramlardan istifadə edin və platformanız üçün mana oxumağı unutmayın!

Mənbə: www.habr.com

Добавить комментарий