Cron — серверда вазифаларни белгиланган вақтда автоматик бажарадиган режалаштирувчи. Хостингда у кўпинча захира нусха олиш, хабарномалар юбориш, валюта курсини янгилаш ёки эски файлларни тозалаш учун ишлатилади. Муаммо шундаки, cron хато қилганда ҳеч нарса демайди: вазифа шунчаки бажарилмайди ва сиз буни бир неча кундан кейин, натижа йўқлигини кўрганингизда биласиз. Шунинг учун биринчи қоида оддий — ҳар бир cron вазифасининг натижасини лог файлга ёзинг, кейин қуйидаги хатоларни бирма-бир текширинг.
Аввал натижани лог файлга йўналтиринг
Cron буйруғи охирига чиқишни файлга йўналтирувчи қисм қўшилса, скрипт нима деганини кейин ўқиш мумкин бўлади. >> белгиси файлга қўшиб ёзади, 2>&1 эса хато хабарларини ҳам шу файлга юборади. Усиз PHP'нинг "Fatal error" хабари ёки "command not found" каби тизим хабари йўқолиб кетади.
*/15 * * * * /usr/bin/php /var/www/user/data/www/misol.uz/cron/kurs.php >> /var/www/user/data/logs/kurs.log 2>&1
Лог файл ўсиб кетмаслиги учун уни вақти-вақти билан тозалаб туринг ёки скрипт ичида фақат муҳим қаторларни ёзинг. Энди ҳар бир хатони кўриб чиқамиз.
1. Нисбий йўл ишлатилган
Скриптни браузерда очганингизда у ўз папкасида ишлайди, cron эса уни фойдаланувчининг уй каталогидан ишга туширади. Шу сабабли скрипт ичидаги include 'config.php' ёки file_put_contents('data/out.txt', ...) каби нисбий йўллар бошқа жойни кўрсатади ва файл топилмайди. Ечим — PHP'да __DIR__ константасидан фойдаланиш ёки буйруқнинг ўзида аввал папкага ўтиш.
*/15 * * * * cd /var/www/user/data/www/misol.uz && /usr/bin/php cron/kurs.php >> /var/www/user/data/logs/kurs.log 2>&1
2. Cron муҳитида PATH қисқа
Терминалда ишлайдиган php, wp ёки composer буйруқлари cron ичида "command not found" бериши мумкин. Сабаби — cron жуда қисқа муҳит ўзгарувчилари билан ишлайди ва сизнинг терминал созламаларингизни юкламайди. Ҳар доим тўлиқ йўлни ёзинг; уни терминалда which php буйруғи билан билиб оласиз.
3. Нотўғри PHP версияси
Хостингда бир нечта PHP версияси ўрнатилган бўлиши мумкин. Сайт панелда PHP 8.2 билан ишлаяпти, лекин cron'даги оддий php буйруғи тизимнинг эски версиясини чақирса, замонавий синтаксисли скрипт дарҳол "syntax error" беради. Керакли версиянинг аниқ йўлини кўрсатинг ва текширинг:
/opt/php82/bin/php -v
Версия йўллари сервердан серверга фарқ қилади, шунинг учун аниқ йўлни панел ёки техник ёрдамдан аниқланг.
4. Бажариш рухсати йўқ ёки қатор охири бузилган
Агар cron'да скриптни тўғридан-тўғри чақирсангиз (масалан, /home/user/backup.sh), файлда бажариш рухсати бўлиши шарт. Бундан ташқари, Windows'да таҳрирланган bash скрипт қатор охирида CRLF белгиларини сақлайди ва Linux уни "bad interpreter" хатоси билан рад этади.
chmod +x /home/user/backup.sh
sed -i 's/\r$//' /home/user/backup.sh
5. Фоиз белгиси экранланмаган
Бу кам маълум, лекин жуда кўп учрайдиган хато. Cronтаб қаторида % белгиси янги қатор маъносини беради, шунинг учун date +%Y-%m-%d каби буйруқ бўлакка бўлиниб кетади. Ҳар бир фоиз белгиси олдига тескари чизиқ қўйинг: date +\%Y-\%m-\%d. Мураккаб буйруқларни эса алоҳида скрипт файлга чиқариш қулайроқ.
6. Вақт ифодаси нотўғри тушунилган
Беш майдон тартиби: дақиқа, соат, ой куни, ой, ҳафта куни. * 3 * * * ёзуви "ҳар куни соат 3 да бир марта" эмас, балки соат 3:00 дан 3:59 гача ҳар дақиқада ишга тушади. Тўғри вариант — 0 3 * * *. Бундан ташқари, сервер вақт минтақаси Тошкент вақтидан фарқ қилиши мумкин; буни date буйруғи билан текшириб, жадвални шунга мосланг.
7. Вазифа ўзи билан устма-уст тушади
Агар скрипт 10 дақиқа ишласа-ю, ҳар 5 дақиқада ишга туширилса, бир вақтда бир нечта нусха ишлай бошлайди. Натижада битта хабар икки марта юборилади ёки базада қулф (lock) хатолари пайдо бўлади. flock буйруғи олдинги нусха тугамагунча янгисини ишга туширмайди:
*/5 * * * * /usr/bin/flock -n /tmp/sms.lock /usr/bin/php /var/www/user/data/www/misol.uz/cron/sms.php >> /var/www/user/data/logs/sms.log 2>&1
8. Вақт ёки хотира чегараси
Катта экспорт ёки захира скрипти хостинг тарифининг хотира ёки процессор чегарасига урилиб, ярмида тўхташи мумкин. Логда "Allowed memory size exhausted" ёки "Killed" сўзлари кўринса, ишни кичик бўлакларга бўлинг: масалан, бир ишга тушишда 500 та ёзувни қайта ишланг. Жуда оғир вазифалар учун уларни тунда, сайт юкламаси кам пайтда режалаштириш ҳам ёрдам беради.
Амалий мисол: Тошкентдаги интернет-дўкон
Кичик маиший техника дўкони ҳар тунда соат 2 да маҳсулот нархларини доллар курсига қараб янгилайдиган скрипт ёзди. Бир ҳафта давомида нархлар ўзгармади, панелда эса cron "фаол" бўлиб турарди. Лог йўналтириш қўшилгач, файлда "Failed opening required 'config.php'" хабари чиқди — скрипт нисбий йўл билан созламани қидирган. Буйруқ бошига cd қўшилгандан кейин кейинги кечаси скрипт ишлади, аммо энди "syntax error" чиқди: cron эски PHP'ни чақираётган эди. Тўлиқ йўл кўрсатилгач, вазифа тўғри ишлай бошлади. Икки хато ҳам фақат лог туфайли 10 дақиқада топилди.
Скриптни cron шароитида қўлда синаш
Вазифани жадвалга қўйишдан олдин уни cron муҳитига яқин шароитда синаб кўринг. Қуйидаги буйруқ деярли бўш муҳит билан ишга туширади ва PATH ёки ўзгарувчиларга боғлиқ муаммоларни дарҳол кўрсатади:
env -i /bin/sh -c 'cd /var/www/user/data/www/misol.uz && /usr/bin/php cron/kurs.php'
sayt.uz хостингида cron вазифалари ISPmanager панелининг "Режалаштирувчи" бўлимида қўшилади, панелга эса sayt.uz кабинетидан кирасиз. Агар лог бўш қолса ва вазифа умуман ишга тушмаётгандек кўринса, техник ёрдамга тикет ёзиб, буйруқ қаторини юборинг — сервер томонидаги cron логини текшириш мумкин.