Cron Linuxissa: historia, käyttö ja laite

Cron Linuxissa: historia, käyttö ja laite

Klassikko kirjoitti, että happy hour ei katso. Noina villeinä aikoina ei ollut ohjelmoijia eikä Unixia, mutta nykyään ohjelmoijat tietävät varmasti: cron seuraa aikaa heidän sijaansa.

Komentoriviohjelmat ovat minulle sekä heikkous että työ. sed, awk, wc, cut ja muita vanhoja ohjelmia ajetaan skripteillä palvelimillamme päivittäin. Monet niistä on suunniteltu tehtäviksi cronille, joka on alun perin 70-luvulta peräisin oleva aikataulu.

Pitkän aikaa käytin cronia pinnallisesti, yksityiskohtiin menemättä, mutta eräänä päivänä, kun törmäsin virheeseen skriptiä ajaessani, päätin perehtyä siihen perusteellisesti. Näin tämä artikkeli ilmestyi, ja sitä kirjoittaessani tutustuin POSIX crontabiin, tärkeimpiin cron-vaihtoehtoihin suosituissa Linux-jakeluissa ja joidenkin niistä rakenteeseen.

Käytätkö Linuxia ja suoritatko cron-tehtäviä? Oletko kiinnostunut järjestelmäsovellusarkkitehtuurista Unixissa? Sitten ollaan matkalla!

Pitoisuus

Lajin alkuperä

Käyttäjä- tai järjestelmäohjelmien säännöllinen suorittaminen on ilmeinen välttämättömyys kaikissa käyttöjärjestelmissä. Siksi ohjelmoijat ymmärsivät kauan sitten, että tarvitaan palveluita, joiden avulla he voivat suunnitella ja suorittaa tehtäviä keskitetysti.

Unixin kaltaiset käyttöjärjestelmät juontavat juurensa Unix-versioon 7, joka kehitettiin viime vuosisadan 70-luvulla Bell Labsissa, mukaan lukien kuuluisa Ken Thompson. Versio 7 Unix sisälsi myös cronin, palvelun säännöllisesti suoritettaviin superkäyttäjätehtäviin.

Tyypillinen nykyaikainen cron on yksinkertainen ohjelma, mutta alkuperäisen version toiminta-algoritmi oli vielä yksinkertaisempi: palvelu heräsi kerran minuutissa, luki taulukon tehtävistä yhdestä tiedostosta (/etc/lib/crontab) ja suoritti sen superuser ne tehtävät, jotka olisi pitänyt suorittaa tällä hetkellä.

Myöhemmin yksinkertaisen ja hyödyllisen palvelun parannetut versiot toimitettiin kaikkien Unix-tyyppisten käyttöjärjestelmien kanssa.

Yleistetyt kuvaukset crontab-formaatista ja apuohjelman toiminnan perusperiaatteista sisällytettiin Unix-tyyppisten käyttöjärjestelmien päästandardiin - POSIXiin - vuonna 1992, jolloin de facto -standardista cronista tuli de jure -standardi.

Vuonna 1987 Paul Vixie, tutkittuaan Unix-käyttäjiä heidän toiveistaan ​​cronille, julkaisi toisen version demonista, joka korjasi joitain perinteisen cronin ongelmia ja laajensi taulukkotiedostojen syntaksia.

Vixie cronin kolmanteen versioon mennessä alkoi täyttää POSIX-vaatimukset, lisäksi ohjelmalla oli vapaa lisenssi, tai pikemminkin lisenssiä ei ollut ollenkaan, paitsi README:n toiveet: kirjoittaja ei anna takuita, tekijän nimi ei voida poistaa, ja ohjelmaa voidaan myydä vain yhdessä lähdekoodin kanssa. Nämä vaatimukset osoittautuivat yhteensopiviksi noina vuosina suosiota saaneiden ilmaisten ohjelmistojen periaatteiden kanssa, joten jotkin 90-luvun alussa ilmestyneistä tärkeimmistä Linux-jakeluista ottivat Vixie cronin järjestelmäkseen ja kehittävät sitä edelleen.

Erityisesti Red Hat ja SUSE kehittävät Vixie cron - cronien haarukan, ja Debian ja Ubuntu käyttävät alkuperäistä Vixie cron -versiota monilla korjaustiedostoilla.

Tutustutaan ensin POSIXissa kuvattuun käyttäjäapuohjelmaan crontab, jonka jälkeen tarkastellaan Vixie cronin syntaksilaajennuksia ja Vixie cronin muunnelmien käyttöä suosituissa Linux-jakeluissa. Ja lopuksi, kirsikka kakun päällä on cron-daemon-laitteen analyysi.

POSIX crontab

Jos alkuperäinen cron toimi aina pääkäyttäjälle, nykyaikaiset ajoitusohjelmat käsittelevät usein tavallisten käyttäjien tehtäviä, mikä on turvallisempaa ja kätevämpää.

Cronit toimitetaan kahden ohjelman sarjana: jatkuvasti käynnissä oleva cron-daemon ja käyttäjien käytettävissä oleva crontab-apuohjelma. Jälkimmäisen avulla voit muokata kunkin järjestelmän käyttäjäkohtaisia ​​tehtävätaulukoita, kun taas demoni käynnistää tehtäviä käyttäjä- ja järjestelmätaulukoista.

В POSIX-standardi demonin käyttäytymistä ei kuvata millään tavalla ja vain käyttäjäohjelma on formalisoitu crontab. Käyttäjien tehtävien käynnistämismekanismien olemassaolo on tietysti implisiittistä, mutta sitä ei kuvata yksityiskohtaisesti.

Kutsumalla crontab-apuohjelman voit tehdä neljä asiaa: muokata käyttäjän tehtävätaulukkoa editorissa, ladata taulukon tiedostosta, näyttää nykyisen tehtävätaulukon ja tyhjentää tehtävätaulukon. Esimerkkejä crontab-apuohjelman toiminnasta:

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

Kun soitat crontab -e vakioympäristömuuttujassa määritettyä editoria käytetään EDITOR.

Itse tehtävät on kuvattu seuraavassa muodossa:

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

Tietueiden viisi ensimmäistä kenttää: minuutit [1..60], tunnit [0..23], kuukauden päivät [1..31], kuukaudet [1..12], viikonpäivät [0. .6], jossa 0 on sunnuntai. Viimeinen, kuudes, kenttä on rivi, jonka tavallinen komentotulkki suorittaa.

Viidessä ensimmäisessä kentässä arvot voidaan luetella pilkuilla eroteltuina:

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

Tai yhdysviivalla:

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

Käyttäjien pääsyä tehtävien ajoitukseen säätelevät POSIXissa cron.allow- ja cron.deny-tiedostot, jotka luettelevat käyttäjät, joilla on pääsy crontabiin, ja käyttäjät, joilla ei ole pääsyä ohjelmaan. Standardi ei säätele näiden tiedostojen sijaintia millään tavalla.

Standardin mukaan käynnistetyille ohjelmille on välitettävä vähintään neljä ympäristömuuttujaa:

  1. HOME - käyttäjän kotihakemisto.
  2. LOGNAME — käyttäjän kirjautuminen.
  3. PATH on polku, josta löydät vakiojärjestelmän apuohjelmat.
  4. SHELL — polku käytettyyn komentotulkkiin.

Erityisesti POSIX ei kerro mitään siitä, mistä näiden muuttujien arvot ovat peräisin.

Myydyin - Vixie cron 3.0pl1

Suosittujen cron-muunnelmien yhteinen esi-isä on Vixie cron 3.0pl1, joka otettiin käyttöön comp.sources.unix-postituslistalla vuonna 1992. Tarkastelemme tämän version pääpiirteitä yksityiskohtaisemmin.

Vixie cron tulee kahdessa ohjelmassa (cron ja crontab). Kuten tavallista, demoni vastaa tehtävien lukemisesta ja suorittamisesta järjestelmän tehtävätaulukosta ja yksittäisten käyttäjien tehtävätaulukoista, ja crontab-apuohjelma vastaa käyttäjätaulukoiden muokkaamisesta.

Tehtävätaulukko ja asetustiedostot

Pääkäyttäjän tehtävätaulukko sijaitsee hakemistossa /etc/crontab. Järjestelmätaulukon syntaksi vastaa Vixie cronin syntaksia sillä poikkeuksella, että sen kuudes sarake osoittaa sen käyttäjän nimen, jonka puolesta tehtävä käynnistetään:

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

Tavalliset käyttäjän tehtävätaulukot sijaitsevat hakemistossa /var/cron/tabs/username ja käyttävät samaa syntaksia. Kun suoritat crontab-apuohjelman käyttäjänä, näitä tiedostoja muokataan.

Käyttäjäluetteloita, joilla on pääsy crontabiin, hallitaan tiedostoissa /var/cron/allow ja /var/cron/deny, joihin sinun tarvitsee vain kirjoittaa käyttäjänimi erilliseen riviin.

Laajennettu syntaksi

Verrattuna POSIX crontabiin, Paul Vixeyn ratkaisu sisältää useita erittäin hyödyllisiä muutoksia apuohjelman tehtävätaulukoiden syntaksiin.

Uusi taulukkosyntaksi on tullut saataville: voit esimerkiksi määrittää viikonpäivät tai kuukaudet nimellä (ma, ti ja niin edelleen):

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

Voit määrittää vaiheen, jolla tehtävät käynnistetään:

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

Vaiheet ja intervallit voidaan sekoittaa:

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

Tuetaan intuitiivisia vaihtoehtoja tavalliselle syntaksille (uudelleenkäynnistys, vuosittain, vuosittain, kuukausittain, viikoittain, päivittäin, keskiyöllä, tunneittain):

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

Tehtävän suoritusympäristö

Vixie cronin avulla voit muuttaa käynnissä olevien sovellusten ympäristöä.

Ympäristömuuttujat USER, LOGNAME ja HOME eivät ole yksinkertaisesti demonin tarjoamia, vaan ne on otettu tiedostosta passwd. PATH-muuttuja on "/usr/bin:/bin" ja SHELL-muuttuja on "/bin/sh". Kaikkien muuttujien paitsi LOGNAME arvoja voidaan muuttaa käyttäjätaulukoissa.

Joitakin ympäristömuuttujia (erityisesti SHELL ja HOME) käyttää cron itse tehtävän suorittamiseen. Tältä voi näyttää bashin käyttäminen tavallisen sh:n sijaan mukautettujen tehtävien suorittamiseen:

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

Lopulta kaikki taulukossa määritellyt ympäristömuuttujat (jota cron käyttää tai joita prosessi tarvitsee) välitetään käynnissä olevaan tehtävään.

Tiedostojen muokkaamiseen crontab käyttää VISUAL- tai EDITOR-ympäristömuuttujassa määritettyä editoria. Jos ympäristössä, jossa crontab ajettiin, ei ole määritetty näitä muuttujia, käytetään "/usr/ucb/vi" (ucb on todennäköisesti Kalifornian yliopisto, Berkeley).

cron Debianissa ja Ubuntussa

Debianin ja johdannaisjakelujen kehittäjät ovat julkaisseet voimakkaasti muokattu versio Vixie cron versio 3.0pl1. Taulukkotiedostojen syntaksissa ei ole eroja, käyttäjille se on sama Vixie cron. Suurin uusi ominaisuus: Tuki syslog, SELinux и PAM.

Vähemmän havaittavissa olevia, mutta konkreettisia muutoksia ovat muun muassa asetustiedostojen ja tehtävätaulukoiden sijainti.

Debianin käyttäjätaulukot sijaitsevat hakemistossa /var/spool/cron/crontabs, järjestelmätaulukko on edelleen siellä - hakemistossa /etc/crontab. Debian-pakettikohtaiset tehtävätaulukot sijoitetaan kansioon /etc/cron.d, josta cron-demoni lukee ne automaattisesti. Käyttäjien pääsynhallintaa ohjaavat /etc/cron.allow- ja /etc/cron.deny-tiedostot.

Oletuskuori on edelleen /bin/sh, joka Debianissa on pieni POSIX-yhteensopiva komentotulkki ajatusviiva, käynnistettiin lukematta asetuksia (ei-interaktiivisessa tilassa).

Itse Cron käynnistetään Debianin uusimmissa versioissa systemd:n ​​kautta, ja käynnistyskonfiguraatio on nähtävissä osoitteessa /lib/systemd/system/cron.service. Palvelukonfiguraatiossa ei ole mitään erikoista, hienovaraisempi tehtävien hallinta voidaan tehdä ympäristömuuttujien kautta, jotka on ilmoitettu suoraan kunkin käyttäjän crontabissa.

cronie RedHatissa, Fedorassa ja CentOS:ssä

cronie — Vixie cron -version 4.1 haarukka. Kuten Debianissa, syntaksi ei ole muuttunut, mutta PAM- ja SELinux-tuki, klusterissa työskentely, tiedostojen seuranta inotifyn avulla ja muita ominaisuuksia on lisätty.

Oletuskokoonpano on tavanomaisissa paikoissa: järjestelmätaulukko on hakemistossa /etc/crontab, paketit sijoittavat taulukonsa kansioon /etc/cron.d, käyttäjätaulukot hakemistoon /var/spool/cron/crontabs.

Daemon toimii systemd-ohjauksen alaisuudessa, palvelun kokoonpano on /lib/systemd/system/crond.service.

Red Hatin kaltaisissa jakeluissa /bin/sh käytetään oletuksena käynnistettäessä, mikä on vakio bash. On huomattava, että kun cron-töitä suoritetaan /bin/sh:n kautta, bash-kuori käynnistyy POSIX-yhteensopivassa tilassa eikä lue mitään lisämäärityksiä toimiessaan ei-interaktiivisessa tilassa.

cronie SLES:ssä ja openSUSEssa

Saksalainen SLES-jakelu ja sen johdannainen openSUSE käyttävät samaa kaveria. Myös täällä oleva demoni käynnistetään systemd:n ​​alla, palvelun kokoonpano sijaitsee hakemistossa /usr/lib/systemd/system/cron.service. Asetukset: /etc/crontab, /etc/cron.d, /var/spool/cron/tabs. /bin/sh on sama bash, joka toimii POSIX-yhteensopivassa ei-interaktiivisessa tilassa.

Vixie cron laite

Nykyaikaiset cronin jälkeläiset eivät ole muuttuneet radikaalisti Vixie croniin verrattuna, mutta ovat silti hankkineet uusia ominaisuuksia, joita ei vaadita ohjelman periaatteiden ymmärtämiseen. Monet näistä laajennuksista ovat huonosti suunniteltuja ja sekoittavat koodin. Paul Vixeyn alkuperäinen cron-lähdekoodi on ilo lukea.

Siksi päätin analysoida cron-laitetta molemmille kehityshaareille yhteisen cron-ohjelman esimerkillä - Vixie cron 3.0pl1. Yksinkertaistan esimerkkejä poistamalla lukemista vaikeuttavat ifdefit ja jättämällä pois pienet yksityiskohdat.

Demonin työ voidaan jakaa useisiin vaiheisiin:

  1. Ohjelman alustus.
  2. Ajettavien tehtävien luettelon kerääminen ja päivittäminen.
  3. Pää cron-silmukka käynnissä.
  4. Aloita tehtävä.

Katsotaanpa niitä järjestyksessä.

Alustus

Käynnistyksen jälkeen cron asentaa prosessiargumenttien tarkistuksen jälkeen signaalinkäsittelijät SIGCHLD ja SIGHUP. Ensimmäinen tekee lokimerkinnän aliprosessin päättymisestä, toinen sulkee lokitiedoston tiedostokuvaajan:

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

Cron-daemon toimii aina yksin järjestelmässä, vain pääkäyttäjänä ja cron-päähakemistosta. Seuraavat kutsut luovat lukkotiedoston demonprosessin PID-tunnuksella, varmistavat, että käyttäjä on oikein, ja vaihda nykyinen hakemisto päähakemistoon:

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

Oletuspolku on asetettu, jota käytetään prosesseja käynnistettäessä:

setenv("PATH", _PATH_DEFPATH, 1);

Sitten prosessi "daemonisoidaan": se luo alikopion prosessista kutsumalla forkia ja uuden istunnon aliprosessissa (kutsumalla setsid). Pääprosessia ei enää tarvita, ja se lopettaa:

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

Pääprosessin lopettaminen vapauttaa lukitustiedoston. Lisäksi tiedoston PID on päivitettävä lapselle. Tämän jälkeen tehtävätietokanta täytetään:

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

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

Sitten cron siirtyy päätyösykliin. Mutta ennen sitä kannattaa katsoa tehtäväluettelon lataaminen.

Tehtävälistan kerääminen ja päivittäminen

Load_database-funktio vastaa tehtäväluettelon lataamisesta. Se tarkistaa pääjärjestelmän crontabin ja käyttäjätiedostojen hakemiston. Jos tiedostot ja hakemisto eivät ole muuttuneet, tehtäväluetteloa ei lueta uudelleen. Muuten alkaa muodostua uusi tehtävälista.

Järjestelmätiedoston lataaminen erityisillä tiedosto- ja taulukkonimillä:

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

Käyttäjätaulukoiden lataaminen silmukassa:

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

Tämän jälkeen vanha tietokanta korvataan uudella.

Yllä olevissa esimerkeissä process_crontab-funktiokutsu varmistaa, että taulukkotiedoston nimeä vastaava käyttäjä on olemassa (ellei se ole pääkäyttäjä), ja kutsuu sitten load_user. Jälkimmäinen lukee jo itse tiedoston rivi riviltä:

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

Tässä joko asetetaan ympäristömuuttuja (muodon VAR=arvo rivit) load_env / env_set-funktioilla tai luetaan tehtävän kuvaus (* * * * * /path/to/exec) load_entry-funktiolla.

Merkintäyksikkö, jonka load_entry palauttaa, on tehtävämme, joka sijoitetaan yleiseen tehtäväluetteloon. Funktio itse suorittaa aikamuodon monisanaisen jäsentämisen, mutta olemme enemmän kiinnostuneita ympäristömuuttujien ja tehtävien käynnistysparametrien muodostamisesta:

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

Pääsilmukka toimii nykyisen tehtäväluettelon kanssa.

Pääsilmukka

Version 7 Unixin alkuperäinen cron toimi yksinkertaisesti: se luki kokoonpanon uudelleen silmukassa, käynnisti tämän hetken tehtävät superkäyttäjänä ja nukkui seuraavan minuutin alkuun. Tämä yksinkertainen lähestymistapa vanhemmissa koneissa vaati liikaa resursseja.

SysV:ssä ehdotettiin vaihtoehtoista versiota, jossa demoni meni nukkumaan joko lähimpään minuuttiin, jolle tehtävä oli määritelty, tai 30 minuutiksi. Tässä tilassa määrityksen uudelleen lukemiseen ja tehtävien tarkistamiseen kului vähemmän resursseja, mutta tehtäväluettelon nopea päivittäminen kävi hankalaksi.

Vixie cron palasi tarkistamaan tehtävälistat kerran minuutissa, onneksi 80-luvun lopulla resursseja oli huomattavasti enemmän tavallisissa Unix-koneissa:

/* первичная загрузка задач */
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-funktio osallistuu suoraan tehtävien suorittamiseen, kutsuen job_runqueue- (luettelo ja suorita tehtävät) ja do_command (suorita jokainen yksittäinen tehtävä) -funktioita. Viimeistä toimintoa kannattaa tarkastella tarkemmin.

Tehtävän suorittaminen

Do_command-funktio suoritetaan hyvällä Unix-tyylillä, eli se tekee haarukan suorittaakseen tehtävän asynkronisesti. Pääprosessi jatkaa tehtävien käynnistämistä, aliprosessi valmistelee tehtäväprosessin:

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

Lapsen_prosessissa on melko paljon logiikkaa: se hyväksyy vakiotulosteet ja virhevirrat, lähettää ne sitten sähköpostiin (jos MAILTO-ympäristömuuttuja on määritetty tehtävätaulukossa) ja lopuksi odottaa, että tehtävän pääprosessi päättyy. saattaa loppuun.

Tehtäväprosessin muodostaa toinen haarukka:

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

Siinä periaatteessa kaikki cron on. Jätin pois joitain mielenkiintoisia yksityiskohtia, esimerkiksi etäkäyttäjien kirjanpidon, mutta hahmottelin pääasia.

loppusanat

Cron on yllättävän yksinkertainen ja hyödyllinen ohjelma, joka on tehty Unix-maailman parhaiden perinteiden mukaisesti. Hän ei tee mitään ylimääräistä, mutta hän on tehnyt työnsä upeasti jo usean vuosikymmenen ajan. Ubuntun mukana tulevan version koodin läpi saaminen kesti vain tunnin, ja minulla oli hauskaa! Toivottavasti pystyin jakamaan sen kanssasi.

En tiedä teistä, mutta olen hieman surullinen huomata, että nykyaikainen ohjelmointi, jolla on taipumus monimutkaistaa ja abstraktisti, ei ole edistänyt tällaista yksinkertaisuutta pitkään aikaan.

Nykyaikaisia ​​vaihtoehtoja cronille on monia: systemd-ajastimet mahdollistavat monimutkaisten järjestelmien järjestämisen riippuvuuksilla, fcronilla voit säädellä resurssien kulutusta joustavammin tehtävien mukaan. Mutta henkilökohtaisesti yksinkertaisin crontab riitti minulle aina.

Lyhyesti sanottuna, rakasta Unixia, käytä yksinkertaisia ​​ohjelmia ja älä unohda lukea alustasi manaa!

Lähde: will.com

Lisää kommentti