Tarkibga o'tish

Lab: "qo'lda ishlaydi, lekin cron ostida ishlamaydi" muammosini diagnostika qilish

cron asoslari va cron muhiti va log'lari maqolalarida cron ostidagi skript muhiti interaktiv shell muhitidan nega farq qilishi tushuntirilgan edi. Bu lab o'sha mavhum ogohlantirishni aniq holatga aylantiradi. U qo'lda ishga tushirilganda haqiqatan ishlaydigan, cron ostida esa haqiqatan muvaffaqiyatsiz bo'ladigan skript yozadi va buning sababini topadigan aniq diagnostika ketma-ketligini bosqichma-bosqich bajaradi. Bu real operatsiyalardagi eng keng tarqalgan cron shikoyati va rejalashtirilgan vazifalar bilan bog'liq har qanday LFCS uslubidagi vazifa aynan shuni tekshirish uchun tuzilgan.

Maqsad va yakuniy natija

Bu lab oxirida sizda ikkita mustaqil skript xatosi — PATH haqidagi taxmin va nisbiy yo'l haqidagi taxmin — tufayli cron ostida jimgina muvaffaqiyatsiz bo'ladigan skript bo'ladi. Yo'q chiqish yo'naltirish boshida ularni butunlay ko'zdan yashiradi. Siz avval nosozlikni ko'rinadigan qilasiz, keyin ikki xatoning har birini navbatma-navbat diagnostika qilib tuzatasiz va nihoyat, taqqoslash uchun xuddi shu vazifani systemd timer sifatida qayta amalga oshirasiz.

Topologiya va boshlang'ich holat

cron o'rnatilgan va ishlab turgan bitta lab VM yoki container (sudo systemctl status cron).

Talablar

Xavfsizlik va snapshot haqida eslatma

Bu lab faqat o'z home katalogingiz ostida fayllar va o'z foydalanuvchingiz uchun crontab yozuvi yaratadi — tizim bo'yicha hech qanday konfiguratsiyaga tegilmaydi. Tozalash oddiy crontab -r va lab katalogini o'chirishdan iborat.

1-qadam: qo'lda mukammal ishlaydigan skript yozish

mkdir -p ~/lab/cron-demo && cd ~/lab/cron-demo
cat <<'EOF' > report.sh
#!/bin/bash
which jq
cd data
cat today.txt | jq .
EOF
chmod +x report.sh
mkdir -p data
echo '{"status": "ok"}' > data/today.txt

Interaktiv ishlashini tekshirish:

cd ~/lab/cron-demo
./report.sh
/usr/bin/jq
{
  "status": "ok"
}

Agar jq o'rnatilmagan bo'lsa, avval uni o'rnating: sudo apt install jq. Skriptga u haqiqatan kerak va bu shu labning mohiyatining bir qismi.

2-qadam: uni cron ostida jadvalga qo'yish va muvaffaqiyatsizlikni kuzatish

crontab -e
* * * * * /home/<username>/lab/cron-demo/report.sh

Bir daqiqa kuting, keyin u haqiqatan biror narsa qilganini tekshiring:

sleep 65
ls -la ~/lab/cron-demo/

Hech qayerda yangi chiqish paydo bo'lmaydi va aniq xato ham yo'q. Bu sukunatning o'zi birinchi va eng muhim belgi: chiqish aniq yozib olinmasa, cron vazifalari standart holatda jimgina muvaffaqiyatsiz bo'ladi. cron muhiti va log'lari maqolasi aynan shu tuzoq haqida ogohlantiradi.

Skript muvaffaqiyatsiz bo'lgan deb taxmin qilishdan oldin avval cron uni umuman ishga tushirishga uringanini tasdiqlang. cron hech qachon ishga tushirmagani sababli (crontab sintaksis xatosi, to'xtatilgan cron servisi yoki noto'g'ri foydalanuvchining crontab’i) chiqish bermagan vazifa ishga tushib, muvaffaqiyatsiz bo'lgan vazifadan butunlay boshqa muammo. cron daemon u ishga tushirgan har bir vazifani log'ga yozadi:

# Debian/Ubuntu: cron logs to syslog / the journal
journalctl -u cron --since "2 minutes ago"
grep CRON /var/log/syslog | tail -5
Jul 29 10:31:01 host CRON[5210]: (user) CMD (/home/user/lab/cron-demo/report.sh)

Skriptingiz nomlangan CMD qatori cron uni jadval bo'yicha ishga tushirganini tasdiqlaydi. Demak, sukunat rejalashtirishdagi nosozlikdan emas, skriptning o'zidan kelyapti va labning qolgan qismi crontab yozuviga emas, skript muhitiga qaratiladi. Umuman CMD qatori bo'lmasa, buning o'rniga skriptga tegishdan oldin crontab’ga (crontab -l va cron servisini tekshiring) e’tibor qaratish kerak.

3-qadam: avval chiqishni yozib olish — boshqa biror narsani diagnostika qilishdan oldin

Noto'g'ri ishlayotgan har qanday cron vazifasi uchun eng foydali birinchi tuzatish — uning nosozliklarini umuman ko'rinadigan qilish:

crontab -e
* * * * * /home/<username>/lab/cron-demo/report.sh >> /home/<username>/lab/cron-demo/cron.log 2>&1

Keyingi ishga tushishni kutgandan keyin tekshirish:

sleep 65
cat ~/lab/cron-demo/cron.log
/home/<username>/lab/cron-demo/report.sh: line 2: jq: command not found
/home/<username>/lab/cron-demo/report.sh: line 3: cd: data: No such file or directory
cat: today.txt: No such file or directory

Endi haqiqiy sabablar ko'rinib turibdi va ular ikkita, bir-biridan mustaqil.

4-qadam: diagnostika va tuzatish — 1-sabab: PATH da jq joylashgan joy yo'q

crontab -l | grep PATH

cron’ning standart PATH i odatda minimal (/usr/bin:/bin) bo'ladi va u odatda /usr/bin ni o'z ichiga oladi. Lekin paket menejeri orqali /usr/local/bin ga, til versiyalari menejeriga yoki maxsus o'rnatish joyiga o'rnatilgan ko'plab vositalar unda bo'lmaydi — aynan cron muhiti va log'lari maqolasida tushuntirilganidek. jq aslida qayerda joylashganini tasdiqlang:

which jq
/usr/bin/jq

Agar tizimingizda bu yo'l haqiqatan cron’ning standart PATH idan tashqarida bo'lsa, uni crontab boshida aniq qo'shing yoki binary’ga skript ichida bevosita to'liq yo'li bilan murojaat qiling. Ikkinchisi ikki tuzatishdan mustahkamrog'i, chunki u crontab qachondir qayta yaratilsa, crontab’dagi PATH qatorining saqlanib qolishiga bog'liq emas:

sed -i 's/^which jq$/which \/usr\/bin\/jq/; s/jq \./\/usr\/bin\/jq ./' ~/lab/cron-demo/report.sh

5-qadam: diagnostika va tuzatish — 2-sabab: ishchi katalog siz taxmin qilganidek emas

cd data qatori skriptning ishchi katalogi ~/lab/cron-demo deb taxmin qilgan. Skript o'sha katalogdan qo'lda ishga tushirilganda bu to'g'ri, lekin cron vazifani crontab yozuvi murojaat qilgan katalogda boshlamaydi. cron muhiti va log'lari maqolasida tushuntirilganidek, skriptning o'zi diskda qayerda joylashganidan qat’i nazar, cron vazifalari odatda buning o'rniga foydalanuvchining home katalogida boshlanadi.

Tuzatish — skript ichida hech qachon ochiq nisbiy yo'l emas, absolyut yo'llardan foydalanish:

cat <<'EOF' > ~/lab/cron-demo/report.sh
#!/bin/bash
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
/usr/bin/jq --version
cd "$SCRIPT_DIR/data"
cat today.txt | /usr/bin/jq .
EOF
chmod +x ~/lab/cron-demo/report.sh

Taxmin qilinmasdan, BASH_SOURCE[0] dan aniqlangan SCRIPT_DIR skriptning o'z joylashuvini uning ichidagi har bir nisbiy murojaat uchun tayanch nuqtaga aylantiradi. Bu skript qaysi katalogdan chaqirilishidan — interaktiv, cron’dan yoki systemd unit’idan — qat’i nazar to'g'ri ishlaydi.

Tekshirish:

> ~/lab/cron-demo/cron.log
sleep 65
cat ~/lab/cron-demo/cron.log
jq-1.7
{
  "status": "ok"
}

6-qadam: xuddi shu vazifani systemd timer sifatida qayta amalga oshirish

# ~/.config/systemd/user/report.service
[Unit]
Description=Run report.sh

[Service]
Type=oneshot
ExecStart=/home/<username>/lab/cron-demo/report.sh
# ~/.config/systemd/user/report.timer
[Unit]
Description=Run report.sh every minute

[Timer]
OnCalendar=*-*-* *:*:00
Persistent=true

[Install]
WantedBy=timers.target
systemctl --user daemon-reload
systemctl --user enable --now report.timer

Tekshirish:

systemctl --user list-timers
journalctl --user -u report.service -n 10
jq-1.7
{
  "status": "ok"
}

E’tibor bering, diagnostika tajribasi darhol yaxshiroq: journalctl --user -u report.service vazifaning chiqishi va exit status’ini qo'lda chiqish yo'naltirishni talab qilmasdan bevosita ko'rsatadi. systemd timer’lar maqolasi juda oddiy vazifadan tashqari har qanday narsa uchun oddiy cron’ga nisbatan aynan shu afzallikni ta’kidlaydi.

Keng tarqalgan xatolar

  • Skriptning interaktiv muvaffaqiyati uning cron’dagi muvaffaqiyatini oldindan aytib beradi deb o'ylash. Bu lab bevosita ko'rsatganidek, interaktiv shell’ning PATH i ham, ishchi katalogi ham cron’ning minimal standartlaridan boyroq. Ulardan biriga yashirin tayanadigan skript har bir qo'lda sinovdan o'tishi va baribir cron ostida muvaffaqiyatsiz bo'lishi mumkin.
  • Avval chiqishni yozib olmasdan diagnostika qilish. 3-qadamdagi yo'naltirish noto'g'ri ishlayotgan har qanday cron vazifasiga kiritiladigan eng birinchi o'zgarish bo'lishi kerak. Faqat sukunatga asoslanib ko'r-ko'rona diagnostika qilish haqiqiy xato matnini o'qishga qaraganda vaqtni behuda sarflaydi.
  • Belgini tuzatib (PATH ga bitta yo'q binary’ni qo'shib), xuddi shu skriptdagi ikkinchi, mustaqil sababni tekshirmaslik. Bu labda ikkita alohida xato bor edi. Faqat birinchisini tuzatish vazifani hali ham jimgina muvaffaqiyatsiz holda qoldirgan bo'lardi.

Orqaga qaytarish va tozalash

crontab -r
systemctl --user disable --now report.timer
rm -f ~/.config/systemd/user/report.service ~/.config/systemd/user/report.timer
systemctl --user daemon-reload
rm -rf ~/lab/cron-demo

Yakuniy baholash mezoni

Quyidagilarning hammasi bajarilsa, bu lab yakunlangan hisoblanadi:

  • siz qo'lda mukammal ishlaydigan skript cron ostida nega aynan shunday muvaffaqiyatsiz bo'lishi mumkinligining ikkita aniq sababini yoddan ayta olasiz;
  • tuzatilgan skriptda nisbiy yo'llar ham, PATH ga bog'liq ochiq buyruq nomlari ham yo'q;
  • systemd timer ekvivalenti muvaffaqiyatli ishlaydi va uning chiqishi qo'lda yo'naltirishsiz journalctl --user -u report.service orqali ko'rinadi.

Mashqlar

  1. Crontab yozuvidan chiqish yo'naltirishni yana olib tashlang, ikki xatodan birini ataylab qayta kiriting va tuzatishga qaytib qaramasdan, faqat shu labdagi jarayondan foydalanib uni diagnostika qilish qancha vaqt olishini o'lchang.
  2. Crontab boshiga MAILTO="" qo'shing va cron muhiti va log'lari maqolasiga tayanib, bu qator cron vazifa chiqishi haqida qanday xabar berishida nimani o'zgartirishini tushuntiring.
  3. Lab mashinasidagi haqiqiy, mavjud cron vazifasini (yoki shu kursdagi oldingi loyihadan birini, masalan, Backup skripti ni) systemd timer’ga aylantiring va ataylab kiritilgan nosozlikdan keyin diagnostika qilish qulayligi bo'yicha ikkalasini yonma-yon taqqoslang.

Manbalar