SSD Nodes Learn Hosting plans →
নির্দেশিকা Matt Connorদ্বারা Matt Connor · আপডেট করা হয়েছে 2026-09-04

Cron job কেন চলে না: 5টি কারণ ও সমাধান

Cron job না চলার 5টি কারণ দেখুন: সীমিত PATH, escape না-করা percent sign, ভুল crontab, mail-এ হারানো output এবং shell ধরে নেওয়া script।

আপনার cron job কেন চলে না

যে cron job “কখনো চলে না”, সেটি প্রায় সব সময়ই আসলে চলেছে। এটি আপনার shell-এর মতো নয় এমন একটি environment-এ চলেছে, প্রথম সেকেন্ডেই ব্যর্থ হয়েছে, এবং বার্তাটি এমন জায়গায় গেছে যা আপনি দেখছেন না। প্রায় সব report-এর পেছনে 5টি কারণ থাকে: search path, percent sign, ভুল crontab file, mail-এ চলে যাওয়া output, এবং login session প্রত্যাশা করা script।

cron হলো একটি daemon (background service), যা crontab file পড়ে এবং নির্ধারিত সময়সূচি অনুযায়ী command চালায়। এটি আপনার .bashrc পড়ে না, terminal খোলে না, login shell চালু করে না এবং কোনো command ব্যর্থ হলে আপনাকে জানায় না। নিচের প্রতিটি কারণ এই 4টি তথ্য থেকেই আসে।

এগুলো ক্রমানুসারে পরীক্ষা করুন। প্রথমে সবার মূল প্রশ্নটি করুন: cron কি আদৌ কাজটি চালু করেছিল? “cron job শুরুই করেনি” এবং “job শুরু হয়ে বন্ধ হয়ে গেছে”—এগুলো সম্পূর্ণ ভিন্ন সমস্যা। এদের মধ্যে কোনো সাধারণ কারণ নেই। তাই প্রথমে সেটির উত্তর নির্ধারণ করুন।

Cron আদৌ চালু হয়েছিল কি?

বিভিন্ন distribution family-তে 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 নামে ডাকে। কোনো নির্দিষ্ট মেশিনে এই দুই নামের মধ্যে একটিই থাকে। তাই দুটি command-এর একটিতে unknown unit দেখানো স্বাভাবিক এবং এটি কোনো ত্রুটি নয়।

আপনার নিজের system যে entry লিখেছে, সেগুলো পড়ুন। কোনো guide থেকে কপি করা line খুঁজবেন না, কারণ cron implementation এবং logging setup ভেদে wording আলাদা হয়। আপনাকে শুধু দুটি বিষয় পরীক্ষা করতে হবে: আপনার schedule-এ নির্ধারিত minute-এ কোনো entry আছে কি না, এবং সেই entry-তে আপনার command-এর নাম আছে কি না। আপনার command-এর নাম থাকা entry-এর অর্থ cron তার কাজ করেছে এবং ব্যর্থতা command-এর ভেতরে। কোনো entry না থাকার অর্থ cron আপনার schedule পায়নি। এটি নিচের cause 3।

কিছু image cron message journal-এর বদলে rsyslog-এর মাধ্যমে একটি file-এ পাঠায়। /var/log-এ cron বা syslog-এর নামে কোনো file আছে কি না দেখুন, তারপর তার শেষের অংশ পড়ুন।

ls -l /var/log
sudo tail -n 50 /var/log/syslog

unit এবং log—কোনোটিই না থাকলে cron সম্ভবত installed নয়। Minimal cloud image এবং container-এ প্রায়ই cron বাদ দেওয়া থাকে।

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 দিয়ে command শুরু করে। তাই standard system directory-এর বাইরে থাকা কোনো program খুঁজে পাওয়া যায় না। /usr/local/bin, /opt-এর অধীনে থাকা যেকোনো কিছু, কোনো language version manager, Python virtual environment বা Go workspace এর সম্ভাব্য উদাহরণ। job-এর প্রথম line-এই ব্যর্থতা ঘটে। যে shell command-টি চালায়, তার ওপর নির্ভর করে shell "not found" ধরনের error-এর সঠিক wording লিখে।

আপনার job যে প্রতিটি command ব্যবহার করে, তার প্রকৃত path খুঁজে বের করুন।

command -v docker
command -v node
readlink -f "$(command -v node)"

এরপর job-এ সেই absolute path-গুলো লিখুন, অথবা 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-এর ভিতরেই শুধু বিদ্যমান এমন সব entry বাদ দিন। এখানে একটি নিয়ম গুরুত্বপূর্ণ: cron এই assignment line-গুলোতে variable expand করে না। PATH=$PATH:/usr/local/bin-এ $PATH:/usr/local/bin-এর literal text সংরক্ষিত হয়। ফলে job-এর search path-এ কোনো ব্যবহারযোগ্য directory থাকে না। পুরো তালিকাটি সরাসরি লিখুন।

একটি version manager-এর জন্য শুধু path যথেষ্ট নয়। nvm, pyenv, rbenv এবং asdf আপনার .bashrc থেকে একটি shell function বা shims directory install করে। cron job কখনোই ওই file পড়ে না। versioned binary-টি absolute path দিয়ে call করুন, অথবা নিজের script-এর প্রথম line হিসেবে version manager-এর init script source করুন।

কারণ 2: percent চিহ্ন আপনার command শেষ করে

crontab-এর command field-এ % সাধারণ character নয়। escape না করা প্রথম % command শেষ করে। এর পরের সবকিছু command-এর standard input হিসেবে পাঠানো হয়, এবং পরবর্তী প্রতিটি % একটি নতুন লাইনে পরিণত হয়। ছোট input কোনো program-এ পাঠানোর জন্য এটি cron-এর একটি বাস্তব feature। date-stamped filename-কে classic broken crontab entry বানানোর কারণও এটাই।

0 3 * * * /usr/bin/tar -czf /srv/backups/site-$(date +%F).tar.gz /srv/site লিখলে tar কখনো formatted date দেখতে পায় না। cron প্রথম %-এ line কেটে দেয়। ফলে shell একটি অসম্পূর্ণ command substitution পায়, আর আপনার line-এর বাকি অংশ standard input হিসেবে পৌঁছায়। প্রতিটি percent-এর আগে backslash দিন।

0 3 * * * /usr/bin/tar -czf /srv/backups/site-$(date +\%F).tar.gz /srv/site

একটি line ধারাবাহিকভাবে দুইটি layer পড়ে। \% হলো cron rule, যা cron কোনো কিছু start করার আগে প্রয়োগ করে। $(date +\%F) হলো command substitution, যা cron start করা shell পরে প্রয়োগ করে। কোন character কোন layer-এর নিয়ন্ত্রণে, তা বোঝাই পুরো বিষয়টির মূল কৌশল।

নিরাপদ পদ্ধতি হলো crontab-এর বাইরে logic রাখা। এটি একটি script-এ রাখুন, যেখানে percent চিহ্নের কোনো বিশেষ অর্থ নেই।

#!/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 count-সহ একাধিক file থাকে। ভুল file-এ job লিখলে সেটি কার্যত অদৃশ্য থাকে।

  • crontab -e যে user command-টি চালায়, তার crontab সম্পাদনা করে। sudo crontab -e root-এর crontab সম্পাদনা করে। একই server debug করার সময় দুই ব্যক্তি প্রায়ই দুইটি আলাদা file পড়েন।
  • sudo crontab -l -u deploy অন্য user-এর crontab দেখায়। যে account-এর job চালানোর কথা, তার জন্য আসলে কী install করা আছে, তা নিশ্চিত করার উপায় এটি।
  • /etc/crontab এবং /etc/cron.d-এর প্রতিটি file-এ schedule ও command-এর মধ্যে একটি অতিরিক্ত field থাকে: job-টি যে user হিসেবে চালাতে হবে। পাঁচটি field-যুক্ত user crontab-এর line /etc/cron.d-এ paste করলে command-এর প্রথম শব্দটিকে username হিসেবে পড়া হয়।
  • /etc/cron.d-এর file-এর নাম কেবল letters, digits, underscores এবং hyphens দিয়ে গঠিত হতে হবে। backup.sh বা site.conf নামের file শুধু নামের কারণেই বাদ পড়ে। সেটির নাম backup করুন এবং আবার log পরীক্ষা করুন।
  • /etc/cron.d-এর file-এর owner root হওয়া উচিত এবং group বা অন্যদের জন্য writable হওয়া যাবে না। ls -l /etc/cron.d একসঙ্গে এই দুই তথ্য দেখায়।
  • /etc/cron.daily এবং তার সমজাতীয় directory-তে রাখা script-গুলো একই naming rule অনুসরণ করে এবং তাদের execute bit-ও থাকতে হবে। execute bit না থাকলে script নীরবে বাদ পড়ে।
  • /etc/cron.allow এবং /etc/cron.deny নির্ধারণ করে কে crontab install করতে পারবে। আপনার server-এ এদের যেকোনো একটি থাকলে, user-এর crontab ব্যবহারের অনুমতি আছে ধরে নেওয়ার আগে সেটি পড়ুন।

Spool file হাতে সম্পাদনা না করে crontab command ব্যবহার করে user crontab install করুন, কারণ install করার আগে crontab file-টি parse করে। Save করার সময় command যে output দেখায়, তা পড়ুন। এটি file প্রত্যাখ্যান করলে আগের version-ই কার্যকর থাকে এবং আপনার পরিবর্তন প্রয়োগ হয় না। ফলে মনে হয় cron আপনার command উপেক্ষা করছে।

Owner-ই permissions নির্ধারণ করে। root-এর crontab-এর job root-owned file তৈরি করে, ফলে file পড়া application সেটিতে লিখতে নাও পারে। সাধারণ user-এর crontab-এর job root-only directory পড়তে পারে না। কাজের ধরন অনুযায়ী owner নির্বাচন করুন: application maintenance সংশ্লিষ্ট application-এর নিজস্ব account-এ থাকা উচিত। এই কারণেই WordPress wp-cron-এর পরিবর্তে system cron job ব্যবহার করা গুরুত্বপূর্ণ। Job যে file তৈরি করে, তার mode এটি যে umask inherit করে, তা থেকে আসে। এই মানটি আপনার shell-এর umask-এর মতো নাও হতে পারে। তাই job-এর output unreadable হলে umask কীভাবে file permissions নির্ধারণ করে পড়ুন।

কারণ 4: আউটপুট এমন মেইলে গেছে যা কেউ পড়ে না

cron কোনো job standard output এবং standard error-এ যা লিখে, তা সব সংগ্রহ করে। job কিছু লিখলে cron সেই লেখা local mail system-এ পাঠায়। প্রাপক হয় crontab-এর owner, অথবা MAILTO যে ঠিকানা নির্ধারণ করে। সাধারণত সীমিত সুবিধার VPS-এ কোনো MTA (mail transfer agent) ইনস্টল করা থাকে না। তাই কিছুই deliver হয় না। আপনার error অল্প সময়ের জন্য তৈরি হয়েছিল, তারপর কোথাও যায়নি। ভাঙা job-কে নীরব মনে হওয়ার সম্পূর্ণ কারণ এটাই।

এর পরিবর্তে আউটপুট আপনার নিয়ন্ত্রণাধীন একটি ফাইলে পাঠান।

0 3 * * * /usr/local/sbin/backup-site.sh >> /var/log/backup-site.log 2>&1

>> standard output ফাইলে append করে। 2>&1 standard error-কে সেই গন্তব্যে পাঠায়, যেখানে ওই মুহূর্তে standard output যাচ্ছে। তাই redirect-এর পরে এটি লিখতে হবে। উল্টোভাবে, অর্থাৎ 2>&1 >> file লিখলে standard error তার আগের গন্তব্যেই থাকে। আপনি যে error খুঁজছেন, সেটিই তখন ফাইলে পৌঁছায় না।

journal-ও একটি ভালো গন্তব্য। logger আপনার নির্ধারিত tag-এর অধীনে syslog-এ লিখে।

0 3 * * * /usr/local/sbin/backup-site.sh 2>&1 | logger -t backup-site

journalctl -t backup-site দিয়ে তা আবার পড়ুন। এতে job-এর নিজস্ব আউটপুট cron entry-গুলোর পাশে থাকে। ফলে সময়ক্রম সহজে অনুসরণ করা যায়। কোন ব্যক্তি সার্ভারে কোন command চালিয়েছেন, তার রেকর্ডও প্রয়োজন হলে সেটি আলাদা ব্যবস্থা। আপনার সার্ভারে ব্যবহারকারীর command audit করা অংশে তা ব্যাখ্যা করা হয়েছে।

crontab-এর শুরুতে MAILTO="" লিখলে তার নিচের job-গুলোর জন্য mail বন্ধ হয়ে যায়। MAILTO-এ একটি কার্যকর ঠিকানা দিলেই হবে না, কারণ কাজের MTA না থাকলে কোনো লাভ নেই। এর ওপর নির্ভর করার আগে mail সার্ভার থেকে বের হচ্ছে কি না যাচাই করুন।

Debug করার সময় একটি নিয়ম মেনে চলুন: কখনো > /dev/null 2>&1 append করবেন না। প্রায় প্রতিটি crontab-এ এটি সবচেয়ে বেশি ব্যবহৃত line, কিন্তু এটি আপনার হাতে থাকা একমাত্র প্রমাণও ফেলে দেয়। job কাজ করার পর প্রয়োজন হলে এটি আবার যোগ করুন।

কারণ 5: স্ক্রিপ্টটি এমন environment ধরে নেয়, যা cron দেয় না

কমান্ডটি পাওয়া গেলে এবং এর output সংগ্রহ করা হলে, এরপর বাকি থাকে আপনার session যে সুবিধাগুলো স্বয়ংক্রিয়ভাবে দেয়।

  • Shellটি bash নাও হতে পারে। ls -l /bin/sh দিয়ে পরীক্ষা করুন। Debian ও Ubuntu-তে এটি dash নির্দেশ করে। তাই double bracket test, arrays এবং source syntax error দিয়ে ব্যর্থ হয়। স্ক্রিপ্টে #!/bin/bash line দিন এবং স্ক্রিপ্টটি call করুন, অথবা crontab-এর শুরুতে SHELL সেট করুন।
  • Working directory আপনার বর্তমান directory নয়। সর্বত্র absolute path ব্যবহার করুন, অথবা স্ক্রিপ্টের প্রথম line-এ cd দিয়ে directory-তে প্রবেশ করুন। Relative path হলো কোনো job “হাতে চালালে কাজ করে” কিন্তু cron-এ করে না—এর সবচেয়ে সাধারণ একক কারণ।
  • Locale আপনার session-এর locale নয়। Date বা number format করা কিংবা text sort করা যেকোনো কিছু ভিন্ন LANG-এর অধীনে ভিন্ন output তৈরি করতে পারে। পরবর্তী কোনো ধাপ যদি সেই output parse করে, অনুমানের ওপর নির্ভর না করে স্ক্রিপ্টে locale সেট করুন।
  • কোনো TTY (terminal) নেই। Confirmation চাওয়া, editor খোলা বা progress bar দেখানো কোনো command hang করতে বা exit করতে পারে। Tool যে non-interactive flag দেয়, সেটি ব্যবহার করুন।
  • কোনো SSH agent নেই। SSH_AUTH_SOCK cron-এর environment-এ থাকে না। তাই আপনার agent loaded থাকার কারণে আগে কাজ করা ssh বা rsync command এখন authenticate করতে ব্যর্থ হয়। Job-এর জন্য নিজস্ব key দিন এবং সেটির মালিকানা job-এর user-কে দিন।
  • কোনো user session bus নেই। তাই XDG_RUNTIME_DIR সেট না করা পর্যন্ত cron job থেকে systemctl --user ব্যর্থ হয়। একটি system unit ব্যবহার করাই ভালো সমাধান।

Fedora, Rocky এবং Alma-তে আরও একটি সম্ভাব্য কারণ আছে। SELinux cron job-কে সীমাবদ্ধ করে। তাই কোনো অপ্রত্যাশিত label-যুক্ত path-এ job কাজ করলে file permission সঠিক দেখালেও access denied হতে পারে। sudo ausearch -m avc -ts recent দিয়ে denial পরীক্ষা করুন। কিছু বন্ধ করার আগে সার্ভারের জন্য SELinux-এর মৌলিক ধারণা পড়ুন।

cron-এর environment দেখানোর এক মিনিটের probe

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-এর অধীনে আসল job চলে, তার crontab-এ একটি line যোগ করুন। দুই পাশেই absolute path ব্যবহার করুন।

* * * * * /home/deploy/cron-probe.sh >> /home/deploy/cron-probe.log 2>&1

এক মিনিট অপেক্ষা করুন। তারপর /home/deploy/cron-probe.log পড়ে নিজের shell-এ চালানো একই command-এর সঙ্গে তুলনা করুন। PATH line, working directory এবং locale একাই সাধারণত failure-এর কারণ দেখিয়ে দেয়। Setup-এর দুটি বিষয় মনে রাখুন: percent sign-গুলো script-এর ভেতরে আছে, যেখানে cron-এর rule প্রযোজ্য নয়। Log path-টিও এমন হতে হবে, যাতে job-এর user সেখানে লিখতে পারে।

উত্তর পাওয়ার সঙ্গে সঙ্গে crontab-এর সেই line মুছে ফেলুন। প্রতি মিনিটে চলা এবং একটি file-এ append করা job ছোট disk-ও পূর্ণ করে ফেলতে পারে। এটি নীরবে ঘটবে।

সময়সূচিটি কি আপনার উদ্দেশ্য অনুযায়ী সেট করা হয়েছে?

একটি user crontab লাইনের শুরুতে পাঁচটি field থাকে: minute, hour, day of month, month, day of week। এর মধ্যে দুটি field এমনভাবে পরস্পরের সঙ্গে কাজ করে, যা অনেককে বিভ্রান্ত করে।

day of month এবং day of week—দুটিই সীমাবদ্ধ করা থাকলে, অর্থাৎ কোনোটিই * না হলে, cron যেকোনো একটি field মিলে গেলেই job চালায়। 0 0 13 * 5 মানে "শুধু Friday the 13th" নয়। এটি প্রতি মাসের 13 তারিখে midnight-এ এবং প্রতি Friday-তে midnight-এ job চালায়। একটি নির্দিষ্ট দিন পেতে দুটি field-এর একটিকে * রাখুন এবং অন্য field-টি script-এর মধ্যে পরীক্ষা করুন।

cron system timezone ব্যবহার করে। অনেক VPS image UTC (coordinated universal time) হিসেবে configured থাকে। তাই 03:00-এর জন্য schedule করা job 03:00 UTC-তে চলে, যা আপনার স্থানীয় সময়ে বিকেলের মাঝামাঝি হতে পারে। আপনার system আসলে কোন timezone ব্যবহার করছে, তা timedatectl দেখায়। আপনার server-এর output পরীক্ষা করুন; এটি আপনার laptop-এর timezone-এর সঙ্গে মিলে যাবে ধরে নেবেন না।

আরও দুটি schedule-সংক্রান্ত সমস্যা জানা দরকার। @reboot cron নিজে start হওয়ার সময় job চালায়। এটি network ready হওয়ার একই সময় নয়। তাই DNS বা remote host প্রয়োজন এমন job boot-এর সময় ব্যর্থ হতে পারে, কিন্তু পরে manual run-এ সফল হতে পারে। এ ছাড়া, কোনো ধীর job চলমান থাকা অবস্থায় তার আরেকটি instance start হওয়া আটকানোর জন্য cron নিজে কোনো ব্যবস্থা করে না। তাই job-টিকে একটি lock-এর মধ্যে চালান।

*/5 * * * * /usr/bin/flock -n /tmp/backup-site.lock /usr/local/sbin/backup-site.sh >> /var/log/backup-site.log 2>&1

Lock আগে থেকেই held থাকলে flock -n সঙ্গে সঙ্গে থেমে যায়। ফলে প্রথম job-এর ওপর আরেকটি run জমা না হয়ে overlapping run বন্ধ হয়ে যায়।

systemd timer কখন ভালো উপায়

cron একটি কাজ ভালোভাবে করে: নির্দিষ্ট সময়ে একটি command চালানো। অন্য ক্ষেত্রে এটি সীমিত। কোনো redirect ছাড়াই timer journal-এ লগ রাখে। পরে query করা যায় এমন exit status দেয়। network-online.target-এর সঙ্গে ordering নির্ধারণ করা যায়। এছাড়া randomized delay ব্যবহার করা যায়, যাতে একশোটি server একই সেকেন্ডে কাজ শুরু না করে। আপনার job-এর এসব সুবিধার কোনোটি প্রয়োজন হলে, একটি VPS-এ systemd service ও timer ব্যবহার করা crontab line-এর পক্ষে যুক্তি দেওয়ার চেয়ে কম কাজের। service অংশ লেখার সময় এমন একটি প্রশ্নের উত্তর দিতে হয়, যেটি cron কখনও করে না। তা হলো, unit কীভাবে বুঝবে যে কাজটি আসলে শুরু হয়েছে। তাই আগে পড়ুন simple, forking ও notify unit-এর জন্য Type= কী বোঝায়। কারণ default type-এর অধীনে কোনো script নিজে daemonize হলে unit-টি active দেখাতে পারে, কিন্তু তার পেছনে কোনো process নাও থাকতে পারে। Retry behaviour-ও এখানেই নির্ধারণ করুন। কারণ systemd restart policy failure-এর পরে কী হবে তা ঠিক করে, অথচ cron-এর কাছে এই প্রশ্নের কোনো উত্তর নেই।

ছোট job-এর জন্য cron ব্যবহার করুন। Dependency বা 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 path ব্যবহার করুন। crontab-এর শুরুতে অথবা script-এর ভেতরে প্রয়োজনীয় মান সেট করুন। এছাড়া এক মিনিট পরপর চলা একটি 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 ব্যবহার করুন। কিছু image-এ বার্তাগুলো rsyslog-এর মাধ্যমে /var/log-এর অধীন কোনো file-এ পাঠানো হয়। আপনার schedule-এ নির্ধারিত minute-এ একটি entry খুঁজুন এবং সেখানে আপনার command-এর নাম আছে কি না পরীক্ষা করুন। কোনো entry না থাকলে cron কখনও schedule-টি পায়নি। তাই সঠিক crontab সম্পাদনা করেছেন কি না নিশ্চিত করুন। ফলাফল ছাড়া entry থাকলে command শুরু হয়ে বন্ধ হয়ে গেছে। তাই redirect ব্যবহার করে এর output সংরক্ষণ করুন।

crontab-এর ভেতরে date +%Y কাজ নষ্ট করে কেন?

cron command field-এ %-কে বিশেষভাবে বিবেচনা করে। প্রথম unescaped % command-এর সমাপ্তি ঘটায়। এর পরের সবকিছু সেই command-এর standard input হিসেবে পাঠানো হয়। এরপরের প্রতিটি % একটি newline-এ পরিণত হয়। ফলে date-formatted filename আপনার নির্দিষ্ট program-এ পৌঁছায় না। প্রতিটি percent-কে \% হিসেবে escape করুন। অথবা command-টি একটি script-এ সরিয়ে script-টি cron থেকে চালান। কারণ script-এর ভেতরে percent sign-এর কোনো বিশেষ অর্থ নেই।

আমার cron job-এর output কোথায় যায়?

এটি local mail system-এ যায়। প্রাপক হিসেবে crontab-এর owner অথবা MAILTO যে নাম নির্ধারণ করে, তাকে ব্যবহার করা হয়। অধিকাংশ VPS image-এ mail transfer agent ইনস্টল করা থাকে না। তাই message বাতিল হয়ে যায় এবং job-টি নীরব মনে হয়। >> /path/to/log 2>&1 ব্যবহার করে output একটি file-এ redirect করুন। এই ক্রম বজায় রাখুন, যাতে standard error standard output অনুসরণ করে। অথবা logger -t myjob-এর মাধ্যমে pipe করে journalctl -t myjob ব্যবহার করে তা পড়ুন। Debugging চলাকালে > /dev/null 2>&1 ব্যবহার করবেন না।

cron নাকি systemd timer ব্যবহার করা উচিত?

নির্দিষ্ট সময়ে একটি সাধারণ command চালাতে cron ব্যবহার করুন। বিশেষ করে এমন machine-এ job সরিয়ে নেওয়ার প্রয়োজন হতে পারে যেখানে systemd চলে না। Journal-এ redirect ছাড়াই output রাখতে চাইলে timer ব্যবহার করুন। Query করা যায় এমন exit status, network চালু হওয়ার পর ordering, randomized start delay অথবা failure-এর পর retry policy প্রয়োজন হলেও timer ব্যবহার করুন। একই server-এ দুটিই চালানো যায়। তাই প্রয়োজন অনুযায়ী একবারে একটি করে job স্থানান্তর করতে পারেন।