Класік пісаў, што шчаслівых гадзіннікаў не назіраюць. У тыя дзікія часы яшчэ не было ні праграмістаў, ні Unix, але ў нашы дні праграмісты ведаюць цвёрда: замест іх за часам прасочыць cron.
Утыліты каманднага радка для мяне адначасова слабасць і руціна. sed, awk, wc, cut і іншыя старыя праграмы запускаюцца скрыптамі на нашых сэрверах штодня. Многія з іх аформлены ў выглядзе задач для cron, планавальніка родам з 70-х.
Я доўга карыстаўся cron павярхоўна, не ўнікаючы ў дэталі, але аднойчы, сутыкнуўшыся з памылкай пры запуску скрыпту, вырашыў разабрацца грунтоўна. Так з'явілася гэты артыкул, пры напісанні якой я азнаёміўся з POSIX crontab, асноўнымі варыянтамі cron у папулярных дыстрыбутывах Linux і прыладай некаторых з іх.
Выкарыстоўваеце Linux і запускаеце задачы ў cron? Вам цікавая архітэктура сістэмных прыкладанняў у Unix? Тады нам па дарозе!
Перыядычнае выкананне карыстацкіх ці сістэмных праграм - відавочная неабходнасць ва ўсіх аперацыйных сістэмах. Таму запатрабаванне ў сэрвісах, якія дазваляюць цэнтралізавана планаваць і выконваць задачы, праграмісты ўсвядомілі вельмі даўно.
Unix-падобныя аперацыйныя сістэмы вядуць свой радавод ад Version 7 Unix, распрацаванай у 70-х гадах мінулага стагоддзі ў Bell Labs у тым ліку і знакамітым Кенам Томпсанам (ангел. Ken Thompson). Разам c Version 7 Unix пастаўляўся і cron, сэрвіс для рэгулярнага выканання задач суперкарыстальніка.
Тыповы сучасны cron - нескладаная праграма, але алгарытм працы арыгінальнага варыянту быў яшчэ прасцей: сэрвіс прачынаўся раз у хвіліну, чытаў таблічку з задачамі з адзінага файл (/etc/lib/crontab) і выконваў для суперкарыстача тыя задачы, якія трэба было выканаць у бягучую хвіліну .
Пасля ўдасканаленыя варыянты простага і карыснага сэрвісу пастаўляліся з усімі Unix-падобнымі аперацыйнымі сістэмамі.
Абагульненыя апісанні фармату crontab і базавых прынцыпаў працы ўтыліты ў 1992 году былі ўключаны ў галоўны стандарт Unix-падобных аперацыйных сістэм – POSIX – і такім чынам cron са стандарту дэ-факта стаў стандартам дэ-юрэ.
У 1987 годзе Пол Віксі (англ.: Paul Vixie), апытаўшы карыстальнікаў Unix на прадмет пажаданняў да cron, выпусціў яшчэ адну версію дэмана, якая выпраўляе некаторыя праблемы традыцыйных cron і пашырае сінтаксіс файлаў-табліц.
Да трэцяй версіі Vixie cron стаў адказваць патрабаванням POSIX, да таго ж у праграмы была ліберальная ліцэнзія, дакладней не было наогул ніякай ліцэнзіі, калі не лічыць пажаданняў у README: гарантый аўтар не дае, імя аўтара выдаляць нельга, а прадаваць праграму можна толькі разам з зыходным кодам. Гэтыя патрабаванні апынуліся сумяшчальныя з прынцыпамі які набіраў у тыя гады папулярнасць вольнага ПЗ, таму некаторыя ключавыя з якія з'явіліся ў пачатку 90-х дыстрыбутываў Linux узялі Vixie cron у якасці сістэмнага і развіваюць яго дагэтуль.
У прыватнасці, Red Hat і SUSE развіваюць форк Vixie cron – cronie, а Debian і Ubuntu выкарыстоўваюць арыгінальнае выданне Vixie cron са мноствам патчаў.
Давайце для пачатку пазнаёмімся з апісанай у POSIX карыстацкай утылітай crontab, пасля чаго разбяром пашырэнні сінтаксісу, прадстаўленыя ў Vixie cron, і выкарыстанне варыяцый Vixie cron у папулярных дыстрыбутывах Linux. І, нарэшце, вішанька на торце - разбор прылады дэмана cron.
POSIX crontab
Калі арыгінальны cron заўсёды працаваў для суперкарыстача, то сучасныя планавальнікі гушчару маюць справу з задачамі звычайных карыстачоў, што больш бяспечна і зручна.
Сron-ы пастаўляюцца камплектам з двух праграм: стала працавальнага дэмана 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 і карыстачы без доступу да праграмы. Размяшчэнне гэтых файлаў стандарт ніяк не рэгламентуе.
Запускаемым праграмам, паводле стандарту, павінны перадавацца па меншай меры чатыры зменныя асяроддзі:
HOME - хатняя дырэкторыя карыстальніка.
LOGNAME - лагін карыстальніка.
PATH - шлях, па якім можна знайсці стандартныя ўтыліты сістэмы.
SHELL - шлях да выкарыстанага каманднага інтэрпрэтатара.
Характэрна, што POSIX нічога не кажа аб тым, адкуль бяруцца значэнні для гэтых зменных.
Хіт продажаў - Vixie cron 3.0pl1
Агульны продак папулярных варыянтаў cron – Vixie cron 3.0pl1, прадстаўлены ў рассылцы comp.sources.unix у 1992 году. Асноўныя магчымасці гэтай версіі мы і разгледзім падрабязней.
Vixie cron пастаўляецца ў дзвюх праграмах (cron і crontab). Як звычайна, дэман адказвае за чытанне і запуск задач з сістэмнай табліцы задач і табліц задач асобных карыстачоў, а ўтыліта crontab - за рэдагаванне карыстацкіх табліц.
Табліца задач і файлы канфігурацыі
Табліца задач суперкарыстача размешчана ў /etc/crontab. Сінтаксіс сістэмнай табліцы адпавядае сінтаксісу Vixie cron з папраўкай на тое, што ў ёй шостай калонкай указваецца імя карыстальніка, ад асобы якога запускаецца задача:
Табліцы задач звычайных карыстачоў размяшчаюцца ў /var/cron/tabs/username і выкарыстоўваюць агульны сінтаксіс. Пры запуску ўтыліты crontab ад імя карыстальніка рэдагуюцца менавіта гэтыя файлы.
Кіраванне спісамі карыстальнікаў, якія маюць доступ да crontab, адбываецца ў файлах /var/cron/allow і /var/cron/deny, куды дастаткова ўнесці імя карыстальніка асобным радком.
Пашыраны сінтаксіс
У параўнанні з POSIX crontab рашэнне Пола Віксі змяшчае некалькі вельмі карысных мадыфікацый у сінтаксісе табліц задач утыліты.
Стаў даступны новы сінтаксіс табліц: напрыклад, можна ўказваць дні тыдня ці месяцы пайменна (Mon, Tue і гэтак далей):
# Запускается ежеминутно по понедельникам и вторникам в январе
* * * 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 - гэта, верагодна, University of California, Berkeley).
cron у Debian і Ubuntu
Распрацоўнікі Debian і вытворных дыстрыбутываў выпусцілі моцна мадыфікаваную версію версію Vixie cron 3.0pl1. Адрозненняў у сінтаксісе файлаў-табліц няма, для карыстачоў гэта той жа самы Vixie cron. Найбуйнейшыя новыя магчымасці: падтрымка сістэмны часопіс, SELinux и PAM.
З меней прыкметных, але якія адчуваюцца змен - размяшчэнне канфігурацыйных файлаў і табліц задач.
Карыстальніцкія табліцы ў Debian размяшчаюцца ў дырэкторыі /var/spool/cron/crontabs, сістэмная табліца ўсё там жа - у /etc/crontab. Спецыфічныя для пакетаў Debian табліцы задач змяшчаюцца ў /etc/cron.d, адкуль дэман cron іх аўтаматычна счытвае. Упраўленне доступам карыстальнікаў рэгулюецца файламі /etc/cron.allow і /etc/cron.deny.
У якасці каманднай абалонкі па змаўчанні па-ранейшаму выкарыстоўваецца /bin/sh, у ролі якога ў Debian выступае невялікі POSIX-сумяшчальны шэл працяжнік, запушчаны без чытання якой-небудзь канфігурацыі (у неінтэрактыўным рэжыме).
Сам cron у апошніх версіях Debian запускаецца праз systemd, а канфігурацыю запуску можна паглядзець у /lib/systemd/system/cron.service. Нічога асаблівага ў канфігурацыі сэрвісу няма, любое больш тонкае кіраванне задачамі магчыма ажыццявіць праз зменныя асяроддзі, абвешчаныя прама ў crontab кожнага з карыстачоў.
cronie у RedHat, Fedora і CentOS
cronie - форк Vixie cron версіі 4.1. Як і ў Debian, сінтаксіс не змяняўся, але дададзеная падтрымка PAM і SELinux, працы ў кластары, сачэнні за файламі пры дапамозе inotify і іншых магчымасцяў.
Канфігурацыя па змаўчанні знаходзіцца ў звычайных месцах: сістэмная табліца - у /etc/crontabs, пакеты змяшчаюць свае табліцы ў /etc/cron.d, карыстацкія табліцы трапляюць у /var/spool/cron/crontabs.
Дэман запускаецца пад кіраваннем systemd, канфігурацыя сэрвісу - /lib/systemd/system/crond.service.
У Red Hat-падобных дыстрыбутывах пры запуску па змаўчанні выкарыстоўваецца /bin/sh, у ролі якога выступае стандартны bash. Трэба заўважыць, што пры запуску задач cron праз /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 у выкананні Пола Віксі чытаць адно задавальненне.
Таму разбор прылады cron я вырашыў правесці на прыкладзе агульнай для абедзвюх галін развіцця cron праграмы – Vixie cron 3.0pl1. Прыклады я спрашчу, прыбраўшы якія ўскладняюць чытанне ifdef-ы і апусціўшы другарадныя дэталі.
Працу дэмана можна падзяліць на некалькі этапаў:
Ініцыялізацыя праграмы.
Збор і абнаўленне спісу задач для запуску.
Праца галоўнага цыклу cron.
Запуск задачы.
Разбяром іх па парадку.
ініцыялізацыя
Пры запуску пасля праверкі аргументаў працэсу cron усталёўвае апрацоўшчыкі сігналаў SIGCHLD і SIGHUP. Першы ўносіць у лог запіс аб завяршэнні працы даччынага працэсу, другі - зачыняе файлавы дэскрыптар файла-лога:
Дэман cron у сістэме заўсёды працуе адзін, толькі ў ролі суперкарыстальніка і з галоўнай дырэкторыі cron. Наступныя выклікі ствараюць файл-лок з PID-ом працэсу-дэмана, пераконваюцца, што карыстач правільны і змяняюць бягучую дырэкторыю на галоўную:
Выстаўляецца шлях па змаўчанні, які будзе выкарыстоўвацца пры запуску працэсаў:
setenv("PATH", _PATH_DEFPATH, 1);
Далей працэс "дэманізуецца": стварае даччыную копію працэсу выклікам fork і новую сесію ў даччыным працэсе (выклік setsid). У бацькоўскім працэсе больш патрэбы няма - і ён завяршае працу:
switch (fork()) {
case -1:
/* критическая ошибка и завершение работы */
exit(0);
break;
case 0:
/* дочерний процесс */
(void) setsid();
break;
default:
/* родительский процесс завершает работу */
_exit(0);
}
Завяршэнне бацькоўскага працэсу вызваляе лок на файле-локу. Акрамя таго, патрабуецца абнавіць PID у файле на даччыны. Пасля гэтага запаўняецца база задач:
Далей 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;
}
}
Тут альбо выстаўляецца зменная асяроддзі (радкі выгляду VAR=value) функцыямі load_env / env_set, альбо чытаецца апісанне задачы (* * * * * /path/to/exec) функцыяй load_entry.
Сутнасць 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 з Version 7 Unix працаваў зусім проста: у цыкле перачытваў канфігурацыю, запускаў суперкарыстальнікам задачы бягучай хвіліны і спаў да пачатку наступнай хвіліны. Гэты просты падыход на старых машынах патрабаваў зашмат рэсурсаў.
У SysV была прапанавана альтэрнатыўная версія, у якой дэман засынаў альбо да бліжэйшай хвіліны, для якой вызначана задача, альбо на 30 хвілін. Рэсурсаў на перачытванне канфігурацыі і праверку задач у такім рэжыме спажывалася менш, але хутка абнаўляць спіс задач стала няёмка.
Vixie cron вярнуўся да праверкі спісаў задач раз у хвіліну, балазе да канца 80-х рэсурсаў на стандартных 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-стылі, гэта значыць для асінхроннага выканання задачы яна робіць fork. Бацькоўскі працэс працягвае запуск задач, даччыны - займаецца падрыхтоўкай працэсу задачы:
switch (fork()) {
case -1:
/*не смогли выполнить fork */
break;
case 0:
/* дочерний процесс: на всякий случай еще раз пробуем захватить главный лок */
acquire_daemonlock(1);
/* переходим к формированию процесса задачи */
child_process(e, u);
/* по завершению дочерний процесс заканчивает работу */
_exit(OK_EXIT);
break;
default:
/* родительский процесс продолжает работу */
break;
}
У child_process даволі шмат логікі: яна прымае стандартныя струмені высновы і памылак на сябе, каб потым пераслаць на пошту (калі ў табліцы задач паказана зменная асяроддзі MAILTO), і, нарэшце, чакае завяршэнні працы асноўнага працэсу задачы.
Працэс задачы фармуецца яшчэ адным fork:
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. Нейкія цікавыя дэталі, напрыклад улік аддаленых карыстальнікаў, я апусціў, але галоўнае выклаў.
пасляслоўе
Сron - на здзіўленне простая і карысная праграма, выкананая ў лепшых традыцыях свету Unix. Яна не робіць нічога лішняга, але сваю працу выконвае цудоўна на працягу ўжо некалькіх дзесяцігоддзяў. Азнаямленне з кодам той версіі, што пастаўляецца з Ubuntu, заняло не больш за гадзіну, а задавальненні я атрымаў масу! Спадзяюся, я змог падзяліцца ім з вамі.
Не ведаю, як вам, але мне крыху сумна ўсведамляць, што сучаснае праграмаванне з яго схільнасцю да пераўскладнення і пераабстрагавання ўжо даўно не размяшчае да падобнай прастаце.
Існуе мноства сучасных альтэрнатыў cron: systemd-timers дазваляюць арганізаваць складаныя сістэмы з залежнасцямі, у fcron можна гнутчэй рэгуляваць спажыванне рэсурсаў задачамі. Але асабіста мне заўсёды хапала найпростых crontab.
Словам, любіце Unix, выкарыстоўвайце простыя праграмы і не забывайце чытаць маны для вашай платформы!