Cron job क्यों नहीं चल रहा है? मुख्य कारण और समाधान
Cron job के न चलने के पांच मुख्य कारण जानें। इसमें minimal PATH, unescaped percent sign, गलत crontab, lost mail output और shell dependency जैसी समस्याओं का सटीक समाधान दिया गया है।
आपका cron job क्यों नहीं चलता है
एक cron job जो "कभी नहीं चलता", वह लगभग हमेशा चल चुका होता है। यह आपके shell से अलग वातावरण में चला, यह पहली ही सेकंड में विफल हो गया, और इसका संदेश कहीं ऐसी जगह चला गया जिसे आप पढ़ नहीं रहे हैं। पाँच कारण लगभग हर रिपोर्ट की व्याख्या करते हैं: search path, percent sign, गलत crontab file, mail पर गया output, और एक script जिसे login session की अपेक्षा है।
cron एक daemon (एक background service) है जो crontab files को पढ़ता है और एक schedule पर commands शुरू करता है। यह आपकी .bashrc को नहीं पढ़ता है, यह terminal नहीं खोलता है, यह login shell शुरू नहीं करता है, और यह आपको यह नहीं बताता है कि command कब विफल होती है। नीचे दिए गए प्रत्येक कारण उन चार तथ्यों से उत्पन्न होते हैं।
उन्हें क्रम से हल करें, और उन सभी के नीचे दिए गए प्रश्न से शुरुआत करें: क्या cron वास्तव में चला? "cron ने कभी job शुरू नहीं किया" और "job शुरू हुआ और मर गया" दो अलग-अलग समस्याएँ हैं जिनमें कुछ भी समान नहीं है, इसलिए पहले उस प्रश्न का उत्तर दें।
क्या cron चला था?
daemon का नाम अलग-अलग distribution परिवारों पर अलग-अलग होता है। दोनों की जाँच करें, फिर log पढ़ें।
systemctl status cron
systemctl status crond
journalctl -u cron --since "2 hours ago"
journalctl -u crond --since "2 hours ago"Debian और Ubuntu में unit का नाम cron होता है। Fedora, Rocky और Alma में इसे crond कहा जाता है। किसी भी मशीन पर इनमें से केवल एक ही नाम मौजूद होता है, इसलिए दो में से एक command का unknown unit बताना सामान्य है और यह कोई त्रुटि नहीं है।
अपने सिस्टम द्वारा लिखी गई entries को पढ़ें। किसी guide से copy की गई line को न ढूँढें, क्योंकि cron implementations और logging setups के बीच शब्दों का चयन अलग-अलग होता है। आप केवल दो चीजों की जाँच कर रहे हैं: क्या आपके schedule के मिनट पर कोई entry है, और क्या वह entry आपके command का नाम लेती है। यदि entry में आपके command का नाम है, तो इसका मतलब है कि cron ने अपना काम किया और विफलता command के भीतर है। यदि कोई entry नहीं है, तो इसका मतलब है कि cron के पास आपका schedule कभी नहीं था, जो नीचे दिए गए कारण 3 का परिणाम है।
कुछ images cron messages को journal के बजाय rsyslog के माध्यम से एक file में भेजती हैं। /var/log में cron या syslog के नाम वाली file ढूँढें, फिर उसके अंत को पढ़ें।
ls -l /var/log
sudo tail -n 50 /var/log/syslogयदि unit और log दोनों मौजूद नहीं हैं, तो हो सकता है कि cron install ही न हो। Minimal cloud images और containers में अक्सर इसे शामिल नहीं किया जाता है।
dpkg -l cron
rpm -q cronie
sudo apt install cron
sudo dnf install cronie
sudo systemctl enable --now cronकारण 1: cron के पास आपका PATH नहीं है
आपका interactive shell PATH को /etc/profile, ~/.profile, ~/.bashrc और उन सभी फाइलों से बनाता है जिन्हें ये फाइलें source करती हैं। cron job के लिए इनमें से कुछ भी रन नहीं होता है। cron कमांड को अपने स्वयं के छोटे environment के साथ शुरू करता है, इसलिए जो प्रोग्राम मानक सिस्टम डायरेक्टरी के बाहर स्थित होते हैं, वे नहीं मिलते हैं। /usr/local/bin, /opt, कोई language version manager, Python virtual environment या Go workspace के अंतर्गत मौजूद कोई भी चीज़ इसके दायरे में आती है। जॉब अपनी पहली लाइन पर ही विफल हो जाती है, और शेल एक "not found" प्रकार की त्रुटि लिखता है, जिसके सटीक शब्द इस पर निर्भर करते हैं कि कौन सा शेल इसे चला रहा था।
अपनी जॉब द्वारा उपयोग की जाने वाली प्रत्येक कमांड का वास्तविक पाथ (path) खोजें।
command -v docker
command -v node
readlink -f "$(command -v node)"इसके बाद या तो उन absolute paths को जॉब में लिखें, या crontab के शीर्ष पर एक बार PATH सेट करें।
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
0 3 * * * /usr/local/bin/mytool runअपनी मशीन से echo "$PATH" के साथ वह सूची लें और उन चीजों को हटा दें जो केवल interactive session के अंदर मौजूद होती हैं। यहाँ एक नियम मायने रखता है: cron इन assignment लाइनों में variables को expand नहीं करता है। PATH=$PATH:/usr/local/bin शाब्दिक टेक्स्ट $PATH:/usr/local/bin को स्टोर करता है, इसलिए जॉब अंततः एक ऐसे सर्च पाथ के साथ समाप्त होती है जिसमें कोई भी उपयोगी डायरेक्टरी नहीं होती है। पूरी सूची लिखें।
एक version manager को केवल पाथ से अधिक की आवश्यकता होती है। nvm, pyenv, rbenv और asdf आपके .bashrc से एक शेल फंक्शन या shims डायरेक्टरी इंस्टॉल करते हैं, और एक cron job उस फाइल को कभी नहीं पढ़ती है। versioned binary को absolute path द्वारा कॉल करें, या अपनी स्क्रिप्ट की पहली लाइन के रूप में manager की init स्क्रिप्ट को source करें।
कारण 2: प्रतिशत चिह्न (percent sign) आपकी कमांड को समाप्त कर देता है
crontab के कमांड फील्ड में, % कोई सामान्य वर्ण नहीं है। पहला अन-एस्केप्ड % कमांड को समाप्त कर देता है। इसके बाद जो कुछ भी होता है, उसे मानक इनपुट (standard input) के रूप में कमांड को भेज दिया जाता है, और प्रत्येक अतिरिक्त % एक नई लाइन (newline) बन जाता है। यह किसी प्रोग्राम को संक्षिप्त इनपुट देने के लिए एक वास्तविक cron फीचर है, और यही कारण है कि date-stamped फ़ाइलनाम वाली crontab प्रविष्टि अक्सर काम नहीं करती है।
0 3 * * * /usr/bin/tar -czf /srv/backups/site-$(date +%F).tar.gz /srv/site लिखें और tar कभी भी फ़ॉर्मेटेड तारीख नहीं देख पाएगा। cron लाइन को पहले % पर काट देता है, इसलिए शेल को एक अधूरा कमांड सब्स्टीट्यूशन प्राप्त होता है और आपकी लाइन का बाकी हिस्सा मानक इनपुट के रूप में पहुँच जाता है। प्रत्येक प्रतिशत चिह्न को बैकस्लैश के साथ एस्केप करें।
0 3 * * * /usr/bin/tar -czf /srv/backups/site-$(date +\%F).tar.gz /srv/siteदो परतें उस एक लाइन को क्रम में पढ़ती हैं। \% एक cron नियम है, जिसे cron किसी भी चीज़ को शुरू करने से पहले लागू करता है। $(date +\%F) कमांड सब्स्टीट्यूशन है, जिसे बाद में उस शेल द्वारा लागू किया जाता है जिसे cron शुरू करता है। यह जानना कि कौन सा वर्ण किस परत के अंतर्गत आता है, पूरी ट्रिक यही है।
सबसे सुरक्षित आदत यह है कि लॉजिक को crontab से पूरी तरह बाहर रखा जाए। इसे एक स्क्रिप्ट में रखें, जहाँ प्रतिशत चिह्न का कोई विशेष अर्थ नहीं होता है।
#!/bin/bash
set -euo pipefail
stamp="$(date +%F)"
tar -czf "/srv/backups/site-${stamp}.tar.gz" /srv/siteतब crontab लाइन में केवल एक पाथ और एक रीडायरेक्ट होता है, और कुछ नहीं। एक crontab जिसे आप एक नज़र में पढ़ सकते हैं, वह एक ऐसी crontab है जिसे आप आसानी से डीबग कर सकते हैं।
कारण 3: आपने किस crontab को एडिट किया?
कोई एक एकल crontab नहीं होता है। कई फाइलें होती हैं, जिनके मालिक अलग-अलग होते हैं और जिनमें fields की संख्या भी भिन्न होती है। गलत फाइल में लिखा गया जॉब दिखाई नहीं देता है।
crontab -eउस यूजर के crontab को एडिट करता है जो कमांड चलाता है।sudo crontab -eroot के crontab को एडिट करता है। एक ही सर्वर को डीबग करने वाले दो लोग अक्सर दो अलग-अलग फाइलें देख रहे होते हैं।sudo crontab -l -u deployकिसी अन्य यूजर का crontab लिस्ट करता है। इसी तरह आप यह पुष्टि कर सकते हैं कि उस अकाउंट के लिए वास्तव में क्या इंस्टॉल है जिसे जॉब चलाना चाहिए।/etc/crontabऔर/etc/cron.dकी प्रत्येक फाइल में शेड्यूल और कमांड के बीच एक अतिरिक्त field होता है: वह यूजर जिसके रूप में कमांड चलना है। यदि आप पांच-field वाली यूजर crontab लाइन को/etc/cron.dमें पेस्ट करेंगे, तो आपके कमांड का पहला शब्द यूजरनेम के रूप में पढ़ा जाएगा।/etc/cron.dमें मौजूद फाइलों के नाम में केवल अक्षर, अंक, अंडरस्कोर और हाइफन होने चाहिए।backup.shयाsite.confजैसी फाइल को उसके नाम के कारण ही छोड़ दिया जाता है। इसेbackupमें रीनेम करें और अपना लॉग फिर से चेक करें।/etc/cron.dमें मौजूद फाइलें root के स्वामित्व में होनी चाहिए और वे ग्रुप या अन्य लोगों द्वारा लिखने योग्य (writable) नहीं होनी चाहिए।ls -l /etc/cron.dआपको ये दोनों तथ्य एक साथ दिखाता है।/etc/cron.dailyऔर उससे संबंधित डायरेक्टरीज में डाली गई स्क्रिप्ट्स भी नामकरण के इसी नियम का पालन करती हैं और उनमें execute bit सेट होना चाहिए। execute bit न होने पर स्क्रिप्ट को चुपचाप छोड़ दिया जाता है।/etc/cron.allowऔर/etc/cron.denyयह तय करते हैं कि किसे crontab इंस्टॉल करने की अनुमति है। यदि आपके सर्वर पर इनमें से कोई भी मौजूद है, तो यह मानने से पहले कि आपके यूजर को अनुमति है, उसे पढ़ लें।
स्पूल फाइल को हाथ से एडिट करने के बजाय crontab कमांड का उपयोग करके यूजर crontab इंस्टॉल करें, क्योंकि crontab इंस्टॉल करने से पहले फाइल को पार्स (parse) करता है। जब आप सेव करें, तो कमांड द्वारा दिए गए आउटपुट को पढ़ें। यदि वह फाइल को अस्वीकार कर देता है, तो पिछला वर्जन ही सक्रिय रहता है और आपका बदलाव लागू नहीं होता, जो बिल्कुल ऐसा दिखता है जैसे cron आपको अनदेखा कर रहा हो।
मालिक ही अनुमतियां (permissions) भी तय करता है। root के crontab में मौजूद जॉब ऐसी फाइलें बनाता है जिनका मालिक root होता है, और जिन्हें पढ़ने वाला एप्लिकेशन शायद उन पर लिख न सके। एक सामान्य यूजर के crontab में मौजूद जॉब root-only डायरेक्टरी को नहीं पढ़ सकता। मालिक का मिलान कार्य के अनुसार करें: एप्लिकेशन का रखरखाव उसी एप्लिकेशन के अकाउंट के अंतर्गत होना चाहिए, यही WordPress wp-cron को सिस्टम cron जॉब से बदलने के पीछे का तर्क है। आपके जॉब द्वारा बनाई गई फाइलों का मोड उसके द्वारा इनहेरिट किए गए umask से आता है, और यह वह वैल्यू है जो आपके शेल से अलग हो सकती है। इसलिए यदि जॉब का आउटपुट अपठनीय (unreadable) रहता है, तो umask फाइल अनुमतियां कैसे सेट करता है पढ़ना उपयोगी होगा।
कारण 4: आउटपुट ऐसे मेल पर गया जिसे कोई नहीं पढ़ता
cron किसी जॉब द्वारा standard output और standard error पर लिखे गए हर डेटा को इकट्ठा करता है। यदि जॉब ने कुछ भी लिखा है, तो cron उस टेक्स्ट को स्थानीय मेल सिस्टम को सौंप देता है, जो crontab के मालिक या MAILTO में निर्दिष्ट पते पर भेजा जाता है। एक न्यूनतम VPS पर आमतौर पर कोई MTA (mail transfer agent) इंस्टॉल नहीं होता, इसलिए कुछ भी डिलीवर नहीं होता। आपकी त्रुटि एक पल के लिए मौजूद थी और फिर कहीं नहीं गई। यही कारण है कि एक खराब जॉब शांत दिखाई देती है।
इसके बजाय आउटपुट को एक ऐसी फाइल में भेजें जिसे आप नियंत्रित करते हैं।
0 3 * * * /usr/local/sbin/backup-site.sh >> /var/log/backup-site.log 2>&1>> standard output को फाइल में जोड़ता (append करता) है। 2>&1 standard error को उस स्थान पर निर्देशित करता है जहाँ अभी standard output है, इसलिए इसे रीडायरेक्ट के बाद आना चाहिए। यदि इसे विपरीत क्रम में लिखा जाए, जैसे 2>&1 >> file, तो standard error अपने मूल गंतव्य पर ही रहता है, और जिस त्रुटि को आप ढूंढ रहे हैं वह कभी फाइल तक नहीं पहुँचती।
journal एक अन्य अच्छा विकल्प है। logger आपके द्वारा चुने गए टैग के तहत syslog में लिखता है।
0 3 * * * /usr/local/sbin/backup-site.sh 2>&1 | logger -t backup-siteइसे journalctl -t backup-site के साथ पढ़ें। यह जॉब के आउटपुट को cron प्रविष्टियों के साथ रखता है, जिससे टाइमलाइन को ट्रैक करना आसान हो जाता है। यदि आपको इस बात का रिकॉर्ड भी चाहिए कि सर्वर पर किस व्यक्ति ने कौन सा कमांड चलाया, तो वह एक अलग सिस्टम है, और auditing user commands on your server में इसे कवर किया गया है।
crontab के शीर्ष पर MAILTO="" लगाने से उसके नीचे की जॉब्स के लिए मेल बंद हो जाता है। MAILTO को एक वास्तविक पते पर सेट करना तभी मददगार है जब एक कार्यशील MTA मौजूद हो, इसलिए उस पर निर्भर होने से पहले यह सुनिश्चित करें कि मेल बॉक्स से बाहर जा रहा है।
डीबगिंग के दौरान एक नियम याद रखें: कभी भी > /dev/null 2>&1 न जोड़ें। यह हर crontab में सबसे लोकप्रिय पंक्ति है, और यह आपके पास मौजूद एकमात्र सबूत को नष्ट कर देती है। जब जॉब काम करने लगे, तो आप इसे बाद में वापस लगा सकते हैं।
कारण 5: स्क्रिप्ट ऐसे वातावरण की अपेक्षा करती है जो cron उसे नहीं देता
एक बार जब कमांड मिल जाती है और उसका आउटपुट कैप्चर हो जाता है, तो बाकी वह सब बचता है जो आपका सेशन आपको मुफ्त में देता है।
- शेल bash नहीं हो सकता है।
ls -l /bin/shके साथ जाँचें। Debian और Ubuntu पर यह dash की ओर संकेत करता है, इसलिए double bracket test, arrays औरsourceसिंटैक्स एरर के साथ विफल हो जाते हैं। स्क्रिप्ट को#!/bin/bashलाइन दें और स्क्रिप्ट को कॉल करें, या crontab के शीर्ष परSHELLसेट करें। - वर्किंग डायरेक्टरी वह नहीं है जिसमें आप खड़े थे। हर जगह absolute paths का उपयोग करें, या स्क्रिप्ट की पहली लाइन पर डायरेक्टरी में
cdकरें। एक relative path सबसे आम कारण है कि कोई जॉब "मेरे द्वारा मैन्युअल रूप से चलाने पर काम करती है"। - लोकेल आपके सेशन जैसा नहीं है। कोई भी चीज़ जो तारीख या संख्या को फॉर्मेट करती है, या टेक्स्ट को सॉर्ट करती है, वह अलग
LANGके तहत अलग आउटपुट दे सकती है। यदि बाद का कोई चरण उस आउटपुट को पार्स करता है, तो उम्मीद करने के बजाय स्क्रिप्ट में ही लोकेल सेट करें। - कोई TTY (टर्मिनल) नहीं है। जो कमांड पुष्टि मांगती है, एडिटर खोलती है या प्रोग्रेस बार दिखाती है, वह हैंग हो सकती है या बंद हो सकती है। टूल द्वारा प्रदान किया गया कोई भी non-interactive फ्लैग जोड़ें।
- कोई SSH agent नहीं है।
SSH_AUTH_SOCK, cron के वातावरण में नहीं है, इसलिए एकsshयाrsyncकमांड जो आपके एजेंट के लोड होने के कारण काम करती थी, अब ऑथेंटिकेट करने में विफल हो जाती है। जॉब को उसकी अपनी की (key) दें, जिसका स्वामित्व जॉब के यूजर के पास हो। - कोई यूजर सेशन बस नहीं है, इसलिए cron जॉब से
systemctl --userतब तक विफल रहता है जब तकXDG_RUNTIME_DIRसेट न हो। एक system unit बेहतर समाधान है।
Fedora, Rocky और Alma पर एक और संदिग्ध कारण है। SELinux, cron जॉब्स को सीमित करता है, इसलिए किसी अनपेक्षित लेबल वाले पाथ को छूने वाली जॉब को तब भी अस्वीकार कर दिया जाता है जब फाइल अनुमतियां सही दिखती हों। sudo ausearch -m avc -ts recent के साथ अस्वीकृतियों (denials) की जाँच करें, और किसी भी चीज़ को बंद करने से पहले SELinux basics for a server पढ़ें।
एक मिनट की जांच जो cron के environment को दिखाती है
cron के environment में क्या है, यह अनुमान लगाना बंद करें और इसे सीधे पढ़ें। एक script लिखें जो सब कुछ dump कर दे, उसे हर मिनट चलने के लिए schedule करें, प्रतीक्षा करें, और फिर file को पढ़ें।
cat > /home/deploy/cron-probe.sh <<'EOF'
#!/bin/bash
echo "=== probe ==="
date -Is
pwd
id
echo "SHELL=$SHELL"
echo "LANG=$LANG"
command -v node || echo "node is not on this PATH"
env | sort
EOF
chmod +x /home/deploy/cron-probe.shउस user के crontab में एक line जोड़ें जिसके तहत वास्तविक job चलती है, और दोनों तरफ absolute paths का उपयोग करें।
* * * * * /home/deploy/cron-probe.sh >> /home/deploy/cron-probe.log 2>&1एक मिनट प्रतीक्षा करें, फिर /home/deploy/cron-probe.log को पढ़ें और इसकी तुलना अपने shell में चलाए गए उन्हीं commands से करें। PATH line, working directory और locale अक्सर विफलता का कारण स्वयं स्पष्ट कर देते हैं। setup के दो विवरणों पर ध्यान दें: percent signs script के अंदर रहते हैं, जहाँ cron का नियम लागू नहीं होता, और log path ऐसा है जिसमें job का user लिख सकता है।
जैसे ही आपको उत्तर मिल जाए, उस crontab line को हटा दें। जो job हर मिनट चलती है और file में data append करती है, वह एक छोटी disk को भर देगी, और वह भी चुपचाप।
क्या आप इसी शेड्यूल की बात कर रहे थे?
एक user crontab लाइन पाँच fields से शुरू होती है: minute, hour, day of month, month, और day of week। इनमें से दो fields आपस में इस तरह काम करते हैं जो लोगों को हैरान कर देते हैं।
जब day of month और day of week दोनों प्रतिबंधित (restricted) होते हैं, यानी उनमें से कोई भी * नहीं होता, तो cron उस job को तब चलाता है जब दोनों में से कोई भी field मैच हो जाए। 0 0 13 * 5 का मतलब "Friday the 13th" नहीं है। यह हर महीने की 13 तारीख को आधी रात को और हर शुक्रवार को आधी रात को चलता है। किसी एक विशिष्ट दिन को चुनने के लिए, दोनों में से एक field को * छोड़ दें और script के अंदर दूसरे field का परीक्षण करें।
cron सिस्टम timezone का उपयोग करता है। कई VPS images में डिफ़ॉल्ट रूप से UTC (coordinated universal time) सेट होता है, इसलिए जिस job को आपने 03:00 के लिए शेड्यूल किया है, वह 03:00 UTC पर चलेगी, जो आपकी दोपहर का समय हो सकता है। timedatectl यह प्रिंट करता है कि आपका सर्वर वास्तव में किस timezone का उपयोग कर रहा है। यह मान लेने के बजाय कि यह आपके लैपटॉप से मेल खाता है, अपने सर्वर की सेटिंग की जाँच करें।
शेड्यूल से जुड़ी दो और सावधानियाँ जानना जरूरी है। @reboot तब चलता है जब cron खुद start होता है, जो कि नेटवर्क के तैयार होने का क्षण नहीं होता है। इसलिए, जिस job को DNS या remote host की आवश्यकता होती है, वह boot के समय विफल हो सकती है और बाद में हर manual run पर सफल हो सकती है। और कोई भी चीज एक धीमी job को दोबारा शुरू होने से नहीं रोकती, जबकि उसकी पिछली copy अभी भी चल रही हो। इसे एक lock के साथ सुरक्षित करें।
*/5 * * * * /usr/bin/flock -n /tmp/backup-site.lock /usr/local/sbin/backup-site.sh >> /var/log/backup-site.log 2>&1flock -n तुरंत रुक जाता है जब lock पहले से ही held होता है, इसलिए overlapping run पहली job के ऊपर जमा होने के बजाय रुक जाता है।
जब systemd timer एक बेहतर विकल्प होता है
cron एक काम के लिए अच्छा है: किसी कमांड को एक निश्चित समय पर चलाना। अन्य सभी मामलों में यह कमजोर है। एक timer आपको बिना किसी redirect के journal देता है, एक exit status जिसे आप बाद में query कर सकते हैं, network-online.target के साथ ordering, और एक randomized delay ताकि सौ सर्वर एक ही सेकंड में शुरू न हों। जब आपके job को इनमें से किसी भी चीज की आवश्यकता हो, तो VPS पर systemd service और timer का उपयोग करना crontab लाइन को मैनेज करने से कम मेहनत वाला काम है। Retry behaviour भी यहीं होना चाहिए, क्योंकि systemd restart policies यह तय करती हैं कि विफलता के बाद क्या होगा, और cron के पास इस सवाल का कोई जवाब नहीं है।
छोटे कार्यों के लिए cron का उपयोग जारी रखें। dependencies या retry policy वाले किसी भी काम को timer पर ले जाएँ। दोनों एक ही सर्वर पर चल सकते हैं, इसलिए यह कोई ऐसी migration नहीं है जिसे आपको एक ही बार में पूरा करना हो।
FAQ
मेरा cron job मैन्युअल रूप से चलाने पर काम करता है, लेकिन cron से विफल क्यों हो जाता है?
क्योंकि आपके शेल और cron का environment अलग-अलग होता है। आपका लॉगिन शेल /etc/profile और ~/.bashrc को पढ़ता है, जो PATH, locale और आपके agent variables को सेट करते हैं। cron कमांड को इनमें से किसी के बिना, एक अलग वर्किंग डायरेक्टरी से और कभी-कभी एक अलग शेल के साथ शुरू करता है। हर कमांड के लिए absolute paths का उपयोग करें, जो आपको चाहिए उसे crontab के शीर्ष पर या स्क्रिप्ट के अंदर सेट करें, और एक मिनट का probe job शेड्यूल करें जो env | sort, pwd और id को एक लॉग फ़ाइल में लिखता है, ताकि आप अनुमान लगाने के बजाय cron का वास्तविक environment देख सकें।
मैं यह कैसे जाँचूँ कि cron ने वास्तव में मेरा job चलाया है या नहीं?
daemon का लॉग पढ़ें। Debian और Ubuntu पर journalctl -u cron का उपयोग करें, या Fedora, Rocky और Alma पर journalctl -u crond का उपयोग करें; कुछ इमेजेस संदेशों को rsyslog के माध्यम से /var/log के अंतर्गत एक फ़ाइल में भेजती हैं। उस मिनट पर एक एंट्री देखें जो आपके शेड्यूल में है और सुनिश्चित करें कि वह आपकी कमांड का नाम दिखा रही है। कोई एंट्री न होने का मतलब है कि cron के पास वह शेड्यूल कभी था ही नहीं, इसलिए पुष्टि करें कि आपने सही crontab को एडिट किया है। बिना परिणाम वाली एंट्री का मतलब है कि कमांड शुरू हुई और समाप्त हो गई, इसलिए इसके आउटपुट को रीडायरेक्ट के साथ कैप्चर करें।
crontab के अंदर date +%Y काम क्यों नहीं करता?
cron कमांड फ़ील्ड में % को विशेष मानता है। पहला unescaped % कमांड को समाप्त कर देता है, उसके बाद की हर चीज़ उस कमांड को standard input के रूप में भेजी जाती है, और प्रत्येक अगला % एक नई लाइन बन जाता है। इसलिए date-formatted फ़ाइल नाम उस प्रोग्राम तक कभी नहीं पहुँचता जिसके लिए आपने इसे लिखा था। प्रत्येक प्रतिशत चिह्न को \% के रूप में एस्केप करें, या कमांड को एक स्क्रिप्ट में ले जाएँ और cron से उस स्क्रिप्ट को कॉल करें, क्योंकि स्क्रिप्ट के अंदर प्रतिशत चिह्न का कोई विशेष अर्थ नहीं होता है।
मेरे cron job का आउटपुट कहाँ जाता है?
यह लोकल मेल सिस्टम में जाता है, जो crontab के मालिक को या जो भी MAILTO में नाम दिया गया है, उसे संबोधित होता है। अधिकांश VPS इमेजेस में कोई मेल ट्रांसफर एजेंट इंस्टॉल नहीं होता है, इसलिए संदेश को हटा दिया जाता है और जॉब साइलेंट दिखता है। आउटपुट को >> /path/to/log 2>&1 के साथ एक फ़ाइल में रीडायरेक्ट करें, इस क्रम को बनाए रखें ताकि standard error, standard output का अनुसरण करे, या इसे logger -t myjob के माध्यम से पाइप करें और journalctl -t myjob के साथ वापस पढ़ें। जब तक आप डिबगिंग कर रहे हों, तब तक > /dev/null 2>&1 का उपयोग न करें।
क्या मुझे cron या systemd timer का उपयोग करना चाहिए?
एक निश्चित समय पर साधारण कमांड के लिए cron का उपयोग करें, विशेष रूप से तब जब आपको इसे ऐसी मशीन पर ले जाने की आवश्यकता हो जो systemd नहीं चलाती है। टाइमर का उपयोग तब करें जब आप आउटपुट को बिना रीडायरेक्ट किए journal में चाहते हों, queryable exit status, नेटवर्क चालू होने के बाद ऑर्डरिंग, रैंडम स्टार्ट डिले, या विफलता के बाद retry policy की आवश्यकता हो। दोनों एक ही सर्वर पर चल सकते हैं, इसलिए आप जॉब्स को एक-एक करके मूव कर सकते हैं जैसे-जैसे उनकी आवश्यकता बढ़ती है।