Cron Job کیوں نہیں چلتی؟ 5 عام وجوہات
Cron job کے نہ چلنے کی 5 عام وجوہات جانیں: محدود PATH، غیر محفوظ percent sign، غلط crontab، mail میں گم output، اور shell پر منحصر script۔
آپ کی cron job کیوں نہیں چلتی
جو cron job "کبھی نہیں چلتی"، وہ تقریباً ہمیشہ چل چکی ہوتی ہے۔ وہ ایسے environment میں چلی ہوتی ہے جو آپ کے shell سے مختلف ہوتا ہے، پہلے ہی لمحے میں fail ہو جاتی ہے، اور اس کا message ایسی جگہ چلا جاتا ہے جسے آپ پڑھ نہیں رہے ہوتے۔ تقریباً ہر رپورٹ کی وضاحت پانچ وجوہات سے ہو جاتی ہے: search path، percent sign، غلط crontab file، mail میں جانے والا output، اور وہ script جو login session کی توقع کرتی ہے۔
cron ایک daemon (background service) ہے جو crontab files پڑھتا ہے اور schedule کے مطابق commands شروع کرتا ہے۔ یہ آپ کا .bashrc نہیں پڑھتا، terminal نہیں کھولتا، login shell شروع نہیں کرتا، اور command fail ہونے پر آپ کو نہیں بتاتا۔ ذیل کی ہر وجہ انہی چار حقائق سے نکلتی ہے۔
ان وجوہات کو اسی ترتیب سے دیکھیں، اور سب کے بنیادی سوال سے شروع کریں: کیا cron نے job واقعی چلائی تھی؟ "cron نے job کبھی شروع نہیں کی" اور "job شروع ہوئی اور پھر بند ہو گئی" دو مختلف مسائل ہیں، جن میں کوئی مشترک وجہ نہیں۔ اس لیے پہلے اسی سوال کا جواب دیں۔
کیا cron نے کام شروع بھی کیا؟
مختلف distribution families میں daemon کا unit name مختلف ہوتا ہے۔ دونوں نام چیک کریں، پھر 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 کہتے ہیں۔ کسی مشین پر ان میں سے صرف ایک نام موجود ہوتا ہے، اس لیے دونوں commands میں سے ایک کا unknown unit رپورٹ کرنا معمول ہے اور خرابی نہیں۔
اپنے system کی لکھی ہوئی entries پڑھیں۔ کسی guide سے نقل کی گئی line تلاش نہ کریں، کیونکہ cron implementations اور logging setups کے درمیان wording مختلف ہوتی ہے۔ آپ کو صرف دو چیزیں چیک کرنی ہیں: کیا آپ کے schedule میں مقررہ minute پر کوئی entry موجود ہے، اور کیا اس entry میں آپ کی command کا نام ہے۔ آپ کی 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 /etc/profile، ~/.profile، ~/.bashrc اور ان فائلوں سے source ہونے والی تمام فائلوں سے PATH بناتا ہے۔ cron job کے لیے ان میں سے کوئی بھی عمل نہیں چلتا۔ cron command کو اپنے مختصر environment کے ساتھ شروع کرتا ہے، اس لیے standard system directories سے باہر موجود program نہیں ملتا۔ /usr/local/bin، /opt کے اندر موجود کوئی بھی چیز، language version manager، Python virtual environment یا Go workspace اس کی ممکنہ وجہ ہو سکتا ہے۔ job پہلی line پر fail ہو جاتی ہے، اور shell ایک "not found" قسم کا error لکھتا ہے۔ اس error کے عین الفاظ اس shell پر منحصر ہوتے ہیں جس نے اسے چلایا۔
اپنی job کے استعمال کردہ ہر command کا حقیقی path معلوم کریں۔
command -v docker
command -v node
readlink -f "$(command -v node)"پھر یا تو job میں وہ absolute paths لکھیں، یا crontab کے شروع میں ایک بار PATH مقرر کریں۔
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
0 3 * * * /usr/local/bin/mytool runیہ فہرست اپنی machine سے echo "$PATH" کے ذریعے حاصل کریں اور وہ چیزیں نکال دیں جو صرف interactive session کے اندر موجود ہوتی ہیں۔ یہاں ایک اصول اہم ہے: cron ان assignment lines میں variables کو expand نہیں کرتا۔ PATH=$PATH:/usr/local/bin میں literal text $PATH:/usr/local/bin محفوظ ہوتا ہے، اس لیے job کو ایسا search path ملتا ہے جس میں کوئی قابلِ استعمال directory نہیں ہوتی۔ پوری فہرست واضح طور پر لکھیں۔
version manager کے لیے صرف path کافی نہیں ہوتا۔ nvm، pyenv، rbenv اور asdf آپ کے .bashrc سے shell function یا shims directory install کرتے ہیں، اور cron job اس file کو کبھی نہیں پڑھتی۔ versioned binary کو absolute path کے ذریعے چلائیں، یا اپنی script کی پہلی line کے طور پر manager کی init script کو source کریں۔
وجہ 2: percent sign آپ کی command ختم کرتا ہے
crontab کے command field میں % عام character نہیں ہے۔ پہلا unescaped % command ختم کر دیتا ہے۔ اس کے بعد موجود تمام متن command کو standard input کے طور پر دیا جاتا ہے، اور ہر اگلا % نئی سطر بن جاتا ہے۔ یہ مختصر input کسی program کو دینے کے لیے cron کی حقیقی خصوصیت ہے، اور یہی وجہ ہے کہ date-stamped filename والی crontab entry عموماً خراب ہوتی ہے۔
0 3 * * * /usr/bin/tar -czf /srv/backups/site-$(date +%F).tar.gz /srv/site لکھنے کے باوجود tar کو formatted date نہیں ملتی۔ cron پہلی % پر سطر کاٹ دیتا ہے، اس لیے shell کو نامکمل command substitution موصول ہوتی ہے اور آپ کی سطر کا باقی حصہ standard input کے طور پر پہنچتا ہے۔ ہر percent sign سے پہلے backslash لگائیں۔
0 3 * * * /usr/bin/tar -czf /srv/backups/site-$(date +\%F).tar.gz /srv/siteاس ایک سطر کو دو layers ترتیب وار پڑھتی ہیں۔ \% ایک cron rule ہے، جسے cron کوئی بھی عمل شروع کرنے سے پہلے apply کرتا ہے۔ $(date +\%F) command substitution ہے، جسے بعد میں وہ shell apply کرتی ہے جسے cron شروع کرتا ہے۔ کون سا character کس layer کے اختیار میں ہے، یہ سمجھنا ہی اصل طریقہ ہے۔
زیادہ محفوظ عادت یہ ہے کہ logic کو مکمل طور پر crontab سے باہر رکھیں۔ اسے ایک script میں رکھیں، جہاں percent sign کا کوئی special meaning نہیں ہوتا۔
#!/bin/bash
set -euo pipefail
stamp="$(date +%F)"
tar -czf "/srv/backups/site-${stamp}.tar.gz" /srv/siteاس کے بعد crontab line میں صرف path اور redirect رہتے ہیں۔ ایسی crontab جسے ایک نظر میں پڑھا جا سکے، اسے debug کرنا بھی آسان ہوتا ہے۔
وجہ 3: آپ نے کون سا crontab تبدیل کیا؟
صرف ایک crontab نہیں ہوتا۔ کئی فائلیں ہوتی ہیں، جن کے مالکان اور field counts مختلف ہوتے ہیں۔ غلط فائل میں لکھی گئی job نظر ہی نہیں آتی۔
crontab -eاس user کے crontab میں ترمیم کرتا ہے جو command چلاتا ہے۔sudo crontab -eroot کے crontab میں ترمیم کرتا ہے۔ ایک ہی box کو debug کرنے والے دو افراد اکثر دو مختلف فائلیں پڑھ رہے ہوتے ہیں۔sudo crontab -l -u deployکسی دوسرے user کا crontab دکھاتا ہے۔ اس سے تصدیق ہوتی ہے کہ اس account کے لیے حقیقت میں کیا install ہے جسے job چلانی چاہیے۔/etc/crontabاور/etc/cron.dکے اندر موجود ہر فائل میں schedule اور command کے درمیان ایک اضافی field ہوتی ہے: وہ user جس کے طور پر job چلانی ہے۔ پانچ field والی user crontab line کو/etc/cron.dمیں paste کرنے پر command کا پہلا لفظ username سمجھا جاتا ہے۔/etc/cron.dکے اندر موجود فائلوں کے نام صرف letters، digits، underscores اور hyphens پر مشتمل ہونے چاہییں۔backup.shیاsite.confنام کی فائل صرف اپنے نام کی وجہ سے skip ہو جاتی ہے۔ اسےbackupکے نام سے rename کریں اور دوبارہ log چیک کریں۔/etc/cron.dکے اندر موجود فائلوں کا owner root ہونا چاہیے، اور group یا others کے لیے writable نہیں ہونا چاہیے۔ls -l /etc/cron.dدونوں باتیں ایک ساتھ دکھاتا ہے۔/etc/cron.dailyاور اس کے ساتھ والی directories میں رکھی گئی scripts پر بھی یہی naming rule لاگو ہوتا ہے، اور ان میں execute bit بھی ہونا چاہیے۔ execute bit نہ ہونے پر script خاموشی سے skip ہو جاتی ہے۔/etc/cron.allowاور/etc/cron.denyطے کرتے ہیں کہ کون crontab install کر سکتا ہے۔ اگر آپ کے box پر ان میں سے کوئی فائل موجود ہو تو یہ فرض کرنے سے پہلے اسے پڑھیں کہ آپ کے user کو crontab کی اجازت ہے۔
User crontab install کرنے کے لیے spool file کو ہاتھ سے edit کرنے کے بجائے crontab command استعمال کریں، کیونکہ crontab install کرنے سے پہلے فائل کو parse کرتا ہے۔ Save کرنے کے بعد دیکھیں کہ command آپ کو کیا output واپس دیتا ہے۔ اگر command فائل مسترد کر دے تو پچھلا version فعال رہتا ہے اور آپ کی تبدیلی لاگو نہیں ہوتی۔ یہ صورت بالکل ایسی دکھائی دیتی ہے جیسے cron آپ کو ignore کر رہا ہو۔
Owner permissions بھی طے کرتا ہے۔ root کے crontab میں موجود job ایسی files بناتی ہے جنہیں پڑھنے والی application شاید write نہ کر سکے۔ عام user کے crontab میں موجود job root-only directory کو read نہیں کر سکتی۔ Owner کو کام کے مطابق منتخب کریں: application maintenance اسی application کے account سے ہونی چاہیے۔ یہی WordPress wp-cron کو system cron job سے تبدیل کرنے کی وجہ ہے۔ Job کی بنائی ہوئی files کا mode اسے inherited umask سے ملتا ہے، اور یہ value آپ کے shell کی umask سے مختلف ہو سکتی ہے۔ اس لیے اگر job کا output unreadable ہو تو umask file permissions کیسے مقرر کرتا ہے پڑھنا مفید ہے۔
وجہ 4: output ایسے mailbox میں جا رہا تھا جسے کوئی نہیں پڑھتا
cron ہر وہ چیز جمع کرتا ہے جو کوئی job standard output اور standard error پر لکھتی ہے۔ اگر job نے کچھ بھی لکھا ہو تو cron یہ متن local mail system کے حوالے کر دیتا ہے۔ یہ متن crontab کے مالک یا MAILTO میں متعین پتے کو بھیجا جاتا ہے۔ محدود VPS پر عموماً کوئی MTA (mail transfer agent) نصب نہیں ہوتا، اس لیے یہ متن کہیں deliver نہیں ہوتا۔ آپ کا error ایک لمحے کے لیے موجود رہا اور پھر غائب ہو گیا۔ broken job خاموش دکھائی دینے کی یہی پوری وجہ ہے۔
Output کو ایسی file میں بھیجیں جسے آپ control کرتے ہوں۔
0 3 * * * /usr/local/sbin/backup-site.sh >> /var/log/backup-site.log 2>&1>> standard output کو file کے آخر میں شامل کرتا ہے۔ 2>&1 standard error کو اس جگہ بھیجتا ہے جہاں اس وقت standard output جا رہا ہوتا ہے، اس لیے اسے redirect کے بعد آنا ضروری ہے۔ اگر ترتیب الٹ ہو، یعنی 2>&1 >> file، تو standard error اپنی اصل destination پر ہی رہتا ہے، اور جس error کی آپ تلاش کر رہے ہیں وہی file تک نہیں پہنچتا۔
journal بھی ایک اچھا target ہے۔ logger آپ کے منتخب کردہ tag کے تحت syslog میں لکھتا ہے۔
0 3 * * * /usr/local/sbin/backup-site.sh 2>&1 | logger -t backup-sitejournalctl -t backup-site سے اسے دوبارہ پڑھیں۔ اس طرح job کا اپنا output cron entries کے قریب رہتا ہے، اور timeline آسانی سے follow کی جا سکتی ہے۔ اگر آپ کو یہ record بھی درکار ہو کہ server پر کس شخص نے کون سا command چلایا، تو یہ الگ system ہے، اور اپنے server پر user commands کی auditing میں اس کا احاطہ کیا گیا ہے۔
crontab کے اوپر MAILTO="" رکھنے سے اس کے نیچے موجود jobs کے لیے mail بند ہو جاتی ہے۔ MAILTO کو حقیقی address پر set کرنا صرف اسی صورت میں مفید ہے جب working MTA موجود ہو، اس لیے اس پر انحصار کرنے سے پہلے ثابت کریں کہ mail server سے باہر جا رہی ہے۔
debugging کے دوران ایک اصول یاد رکھیں: کبھی > /dev/null 2>&1 append نہ کریں۔ یہ ہر crontab کی سب سے عام line ہے، اور آپ کے پاس موجود واحد evidence ضائع کر دیتی ہے۔ job کے کام کرنے کے بعد، اگر چاہیں تو اسے دوبارہ شامل کر دیں۔
وجہ 5: اسکرپٹ ایسے environment پر انحصار کرتی ہے جو cron اسے فراہم نہیں کرتا
جب command مل جائے اور اس کا output محفوظ ہو جائے، تو باقی وہ تمام چیزیں ہیں جو آپ کے session میں خود بخود دستیاب ہوتی ہیں۔
- shell لازماً bash نہیں ہوتی۔
ls -l /bin/shسے جانچیں۔ Debian اور Ubuntu میں یہ dash کی طرف اشارہ کرتا ہے، اس لیے double bracket test، arrays اورsourcesyntax error کے ساتھ ناکام ہو جاتے ہیں۔ اسکرپٹ میں#!/bin/bashلائن شامل کرکے اسکرپٹ کو اسی کے ذریعے چلائیں، یا crontab کے شروع میںSHELLمقرر کریں۔ - working directory وہ نہیں ہوتی جہاں آپ موجود تھے۔ ہر جگہ absolute paths استعمال کریں، یا اسکرپٹ کی پہلی لائن میں
cdکے ذریعے directory تبدیل کریں۔ relative path وہ سب سے عام وجہ ہے جس کی بنا پر کوئی job "دستی طور پر چلانے پر کام کرتی ہے"۔ - locale آپ کے session والی نہیں ہوتی۔ جو بھی چیز date یا number کو format کرتی ہے، یا text کو sort کرتی ہے، مختلف
LANGکے تحت مختلف output پیدا کر سکتی ہے۔ اگر اگلا مرحلہ اس output کو parse کرتا ہے تو امید رکھنے کے بجائے اسکرپٹ میں locale مقرر کریں۔ - TTY (terminal) موجود نہیں ہوتی۔ confirmation مانگنے، editor کھولنے یا progress bar دکھانے والی command رک سکتی ہے یا exit ہو سکتی ہے۔ tool کی فراہم کردہ non-interactive flag استعمال کریں۔
- SSH agent موجود نہیں ہوتا۔
SSH_AUTH_SOCKcron کے environment میں شامل نہیں ہوتا، اس لیےsshیاrsynccommand، جو اس لیے کام کرتی تھی کہ آپ کا agent loaded تھا، اب authenticate نہیں کر پاتی۔ job کے لیے الگ key دیں اور اسے job کے user کی ملکیت میں رکھیں۔ - user session bus موجود نہیں ہوتی، اس لیے cron job سے
systemctl --userناکام ہو جاتی ہے جب تکXDG_RUNTIME_DIRمقرر نہ کیا جائے۔ system unit بہتر حل ہے۔
Fedora، Rocky اور Alma پر ایک اور وجہ بھی ہو سکتی ہے۔ SELinux، cron jobs کو محدود کرتا ہے، اس لیے غیر متوقع label والے path کو استعمال کرنے والی job مسترد ہو جاتی ہے، چاہے file permissions درست نظر آئیں۔ sudo ausearch -m avc -ts recent سے denials کی جانچ کریں، اور کچھ بھی بند کرنے سے پہلے سرور کے لیے SELinux کی بنیادی باتیں پڑھیں۔
ایک منٹ کی جانچ جو cron کا ماحول دکھاتی ہے
cron کے ماحول میں موجود چیزوں کے بارے میں اندازے نہ لگائیں؛ اسے پڑھیں۔ ایسی 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 کے طور پر اصل job چلتی ہے، اس user کے crontab میں ایک line شامل کریں۔ دونوں طرف absolute paths استعمال کریں۔
* * * * * /home/deploy/cron-probe.sh >> /home/deploy/cron-probe.log 2>&1ایک منٹ انتظار کریں، پھر /home/deploy/cron-probe.log پڑھیں اور اس کا موازنہ انہی commands کو اپنے shell میں چلا کر حاصل ہونے والے نتیجے سے کریں۔ PATH line، working directory اور locale عموماً failure کی وجہ خود واضح کر دیتے ہیں۔ Setup کی دو تفصیلات نوٹ کریں: percent signs script کے اندر موجود ہیں، جہاں cron کا rule لاگو نہیں ہوتا، اور log path ایسا ہے جس میں job کا user لکھ سکتا ہے۔
جیسے ہی جواب مل جائے، crontab سے یہ line حذف کر دیں۔ ہر منٹ چلنے والی اور file میں append کرنے والی job چھوٹی disk بھر دے گی، اور یہ کام خاموشی سے کرے گی۔
کیا schedule وہی ہے جو آپ کا مطلب تھا؟
صارف کی crontab لائن پانچ fields سے شروع ہوتی ہے: minute، hour، day of month، month، اور day of week۔ ان میں سے دو fields ایک دوسرے کے ساتھ ایسے تعامل کرتی ہیں جو اکثر لوگوں کو حیران کرتا ہے۔
جب day of month اور day of week دونوں restricted ہوں، یعنی دونوں میں سے کوئی بھی * نہ ہو، تو cron job اس وقت چلاتا ہے جب کوئی بھی field match کرے۔ 0 0 13 * 5 کا مطلب "Friday the 13th" نہیں ہے۔ یہ ہر ماہ کی 13 تاریخ کو midnight پر، اور ہر Friday کو midnight پر چلتا ہے۔ صرف ایک مخصوص دن کے لیے دونوں میں سے ایک field کو * رہنے دیں اور دوسری field کو script کے اندر test کریں۔
cron system timezone استعمال کرتا ہے۔ بہت سی VPS images UTC (coordinated universal time) پر configured ہوتی ہیں، اس لیے 03:00 کے لیے scheduled job 03:00 UTC پر چلتی ہے، جو آپ کے مقامی وقت کے مطابق دوپہر کے دوران ہو سکتا ہے۔ timedatectl آپ کے system میں استعمال ہونے والا اصل timezone دکھاتا ہے۔ اندازہ لگانے کے بجائے اپنا timezone دیکھیں؛ ضروری نہیں کہ وہ آپ کے laptop کے timezone جیسا ہو۔
schedule کے دو مزید traps بھی قابلِ توجہ ہیں۔ @reboot اس وقت چلتا ہے جب خود cron start ہوتا ہے۔ یہ network کے ready ہونے کے برابر نہیں ہوتا، اس لیے DNS یا remote host درکار ہونے والی job boot کے وقت fail ہو سکتی ہے اور اس کے بعد ہر manual run پر کامیاب ہو سکتی ہے۔ اسی طرح کوئی چیز slow job کو اس وقت دوبارہ start ہونے سے نہیں روکتی جب اس کی پچھلی copy ابھی چل رہی ہو۔ اسے lock کے اندر wrap کریں۔
*/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 ہونے کی صورت میں فوراً exit کر جاتا ہے۔ اس طرح overlapping run رک جاتی ہے اور پہلی run کے اوپر جمع نہیں ہوتی۔
جب systemd timer بہتر انتخاب ہو
cron ایک کام کے لیے اچھا ہے: مخصوص وقت پر یہ command چلانا۔ باقی معاملات میں یہ محدود ہے۔ timer آپ کو کسی redirect کے بغیر journal، بعد میں معلوم کیا جا سکنے والا exit status، network-online.target کے ساتھ ordering، اور randomized delay فراہم کرتا ہے، تاکہ سو servers ایک ہی second میں start نہ ہوں۔ جب job کو ان میں سے کسی چیز کی ضرورت ہو تو VPS پر systemd service اور timer، crontab line کے دفاع سے کم محنت طلب ہوتا ہے۔ service لکھتے وقت ایک ایسا سوال سامنے آتا ہے جو cron کبھی نہیں پوچھتا: unit کو کیسے معلوم ہوگا کہ کام حقیقت میں start ہو چکا ہے؟ اس لیے پہلے simple، forking اور notify units کے لیے Type= کا مطلب پڑھیں، کیونکہ default type کے تحت خود daemonize ہونے والی script unit کو active دکھاتی رہتی ہے، جبکہ اس کے پیچھے کوئی process نہیں ہوتا۔ Retry behaviour بھی اسی جگہ مقرر ہوتا ہے، کیونکہ systemd restart policies طے کرتی ہیں کہ failure کے بعد کیا ہوگا، جبکہ cron کے پاس اس سوال کا کوئی جواب نہیں ہے۔
چھوٹی jobs کے لیے cron برقرار رکھیں۔ Dependencies یا retry policy رکھنے والی ہر چیز کو timer پر منتقل کریں۔ دونوں ایک ہی server پر چل سکتے ہیں، اس لیے یہ migration آپ کو ایک ہی نشست میں مکمل کرنے کی ضرورت نہیں۔
FAQ
میرا cron job ہاتھ سے چلتا ہے، لیکن cron کے ذریعے کیوں ناکام ہو جاتا ہے؟
کیونکہ آپ کے shell اور cron کا environment مختلف ہوتا ہے۔ آپ کا login shell /etc/profile اور ~/.bashrc پڑھتا ہے، جو PATH، locale اور آپ کے agent variables مقرر کرتے ہیں۔ cron ان میں سے کسی کے بغیر، مختلف working directory سے، اور کبھی مختلف shell کے ساتھ command شروع کرتا ہے۔ ہر command کے لیے absolute paths استعمال کریں، crontab کے آغاز یا script کے اندر مطلوبہ variables مقرر کریں، اور ایک منٹ بعد چلنے والا probe job schedule کریں جو env | sort، pwd اور id کو ایک log file میں لکھے، تاکہ اندازہ لگانے کے بجائے cron کا حقیقی environment پڑھ سکیں۔
میں کیسے جانچوں کہ cron نے واقعی میرا job چلایا تھا؟
daemon کا log پڑھیں۔ Debian اور Ubuntu پر journalctl -u cron استعمال کریں، یا Fedora، Rocky اور Alma پر journalctl -u crond؛ بعض images یہ messages rsyslog کے ذریعے /var/log کے تحت موجود file میں بھیجتی ہیں۔ اس منٹ پر entry تلاش کریں جس کا نام آپ کے schedule میں ہے، اور تصدیق کریں کہ اس میں آپ کی command درج ہے۔ اگر کوئی entry نہ ہو تو cron کو schedule ملا ہی نہیں، اس لیے تصدیق کریں کہ آپ نے درست crontab میں ترمیم کی ہے۔ اگر entry موجود ہو لیکن نتیجہ نہ ہو تو command شروع ہو کر بند ہو گئی؛ اس لیے redirect کے ذریعے اس کا output محفوظ کریں۔
crontab کے اندر date +%Y کیوں ناکام ہو جاتا ہے؟
cron command field میں % کو special character سمجھتا ہے۔ پہلا unescaped % command ختم کر دیتا ہے، اس کے بعد کا تمام متن اس command کو standard input کے طور پر دیا جاتا ہے، اور ہر مزید % newline بن جاتا ہے۔ اس لیے date-formatted filename اس program تک نہیں پہنچتا جس کے لیے آپ نے اسے لکھا تھا۔ ہر percent کو \% کے طور پر escape کریں، یا command کو script میں منتقل کرکے script کو cron سے call کریں، کیونکہ script کے اندر percent sign کا کوئی special meaning نہیں ہوتا۔
میرے cron job کا output کہاں جاتا ہے؟
یہ local mail system کو بھیجا جاتا ہے، اور crontab کے owner یا اس نام کو مخاطب کیا جاتا ہے جسے MAILTO مقرر کرتا ہے۔ زیادہ تر VPS images میں mail transfer agent نصب نہیں ہوتا، اس لیے message ضائع ہو جاتا ہے اور job خاموش دکھائی دیتا ہے۔ output کو >> /path/to/log 2>&1 کے ذریعے ایک file میں redirect کریں، اور ترتیب برقرار رکھیں تاکہ standard error، standard output کے بعد اسی جگہ جائے، یا اسے logger -t myjob کے ذریعے pipe کریں اور journalctl -t myjob سے دوبارہ پڑھیں۔ جب تک debugging جاری ہو، > /dev/null 2>&1 استعمال نہ کریں۔
مجھے cron استعمال کرنا چاہیے یا systemd timer؟
ایک مقررہ وقت پر سادہ command چلانے کے لیے cron استعمال کریں، خاص طور پر جب آپ کو اسے ایسی machine پر منتقل کرنا ہو جو systemd نہیں چلاتی۔ جب آپ output کو redirect کیے بغیر journal میں چاہتے ہوں، exit status کو query کرنا چاہتے ہوں، network کے up ہونے کے بعد ordering درکار ہو، randomized start delay چاہیے ہو، یا failure کے بعد retry policy درکار ہو تو timer استعمال کریں۔ دونوں ایک ہی server پر چل سکتے ہیں، اس لیے jobs کو ایک ایک کرکے منتقل کیا جا سکتا ہے، جب ان کے لیے یہ تبدیلی مناسب ہو۔