SSD Nodes Learn 🎉 VPS $5.50/মাস থেকে
নির্দেশিকা Matt Connorদ্বারা Matt Connor

Cron Job চলছে না? 5টি কারণ ও সমাধান

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

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

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

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

এগুলো ধারাবাহিকভাবে পরীক্ষা করুন এবং সবগুলোর আগে থাকা প্রশ্নটি দিয়ে শুরু করুন: cron কি আদৌ job চালু করেছিল? “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 আছে কি না দেখুন, তারপর file-এর শেষ অংশ পড়ুন।

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

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

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 নিজস্ব সংক্ষিপ্ত environment দিয়ে command চালু করে। তাই standard system directory-এর বাইরে থাকা কোনো program খুঁজে পাওয়া যায় না। /usr/local/bin, /opt-এর অধীনে থাকা কিছু, কোনো language version manager, Python virtual environment অথবা Go workspace—সবই এর অন্তর্ভুক্ত হতে পারে। job-এর প্রথম line-এই ব্যর্থতা ঘটে। কোন shell এটি চালিয়েছে তার ওপর নির্ভর করে 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-এর মধ্যে শুধু বিদ্যমান এমন সবকিছু বাদ দিন। এখানে একটি নিয়ম গুরুত্বপূর্ণ: cron এই assignment line-গুলোতে variable expand করে না। PATH=$PATH:/usr/local/bin আক্ষরিক 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 দিয়ে call করুন, অথবা নিজের script-এর প্রথম line-এ version manager-এর init script source করুন।

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

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

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-সহ একাধিক 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 চালানোর কথা, সেটির জন্য আসলে কী installed আছে তা নিশ্চিত করার এটাই উপায়।
  • /etc/crontab এবং /etc/cron.d-এর প্রতিটি file-এ schedule ও command-এর মধ্যে একটি অতিরিক্ত field থাকে: কোন user হিসেবে job চালাতে হবে। পাঁচটি 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-এর মালিক root হওয়া উচিত এবং group বা অন্য user-এর জন্য writable হওয়া যাবে না। ls -l /etc/cron.d একসঙ্গে দুটি তথ্যই দেখায়।
  • /etc/cron.daily এবং এর সমজাতীয় directory-তে রাখা script-গুলোকেও একই naming rule মানতে হয় এবং execute bit থাকতে হয়। execute bit না থাকলে job নীরবে বাদ পড়ে।
  • /etc/cron.allow এবং /etc/cron.deny নির্ধারণ করে কে crontab install করতে পারবে। আপনার server-এ এদের কোনোটি থাকলে user-এর অনুমতি আছে ধরে নেওয়ার আগে সেটি পড়ুন।

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

মালিকই permission নির্ধারণ করে। root-এর crontab-এর job root-owned 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 permission নির্ধারণ করে তা পড়া উপকারী।

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

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

এর বদলে output আপনার নিয়ন্ত্রণাধীন একটি file-এ পাঠান।

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

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

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

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

journalctl -t backup-site দিয়ে তা আবার পড়ুন। এতে job-এর নিজস্ব output cron entry-গুলোর পাশে থাকে, তাই সময়ক্রম সহজে অনুসরণ করা যায়। box-এ কোন ব্যক্তি কোন command চালিয়েছে তার record-ও প্রয়োজন হলে, সেটি আলাদা ব্যবস্থা। আপনার server-এ user command audit করা অংশে এ বিষয়ে বলা হয়েছে।

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

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

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

Command খুঁজে পাওয়া এবং তার output সংগ্রহ করার পরে বাকি থাকে আপনার session যে অতিরিক্ত সুবিধাগুলো স্বয়ংক্রিয়ভাবে দেয়।

  • Shell-টি bash নাও হতে পারে। ls -l /bin/sh দিয়ে পরীক্ষা করুন। Debian এবং Ubuntu-তে এটি dash নির্দেশ করে। তাই double bracket test, arrays এবং source syntax error দিয়ে ব্যর্থ হয়। স্ক্রিপ্টে একটি #!/bin/bash line দিন এবং স্ক্রিপ্টটি সেইভাবে চালান, অথবা crontab-এর শুরুতে SHELL সেট করুন।
  • Working directory আপনার বর্তমান directory নয়। সর্বত্র absolute path ব্যবহার করুন, অথবা স্ক্রিপ্টের প্রথম line-এ cd দিয়ে directory পরিবর্তন করুন। কোনো job হাতে চালালে কাজ করে, কিন্তু cron-এ কাজ করে না—এর সবচেয়ে সাধারণ একক কারণ হলো relative path।
  • Locale আপনার session-এর locale নয়। 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_SOCK cron-এর environment-এ থাকে না। তাই আপনার agent loaded থাকার কারণে আগে কাজ করা কোনো ssh বা rsync command এখন authenticate করতে ব্যর্থ হয়। Job-এর জন্য আলাদা key দিন এবং সেটির owner হিসেবে 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 পরীক্ষা করুন। কোনো কিছু বন্ধ করার আগে একটি server-এর জন্য SELinux-এর মৌলিক বিষয়গুলো পড়ুন।

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

cron-এর environment-এ কী আছে, তা অনুমান করা বন্ধ করে সরাসরি পড়ুন। সবকিছু dump করে এমন একটি script লিখুন, সেটি প্রতি মিনিটে চালানোর জন্য 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-এ উভয় পাশে absolute path ব্যবহার করে একটি line যোগ করুন।

* * * * * /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-এর একটিকে * রাখুন এবং অন্যটি script-এর ভিতরে পরীক্ষা করুন।

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

শিডিউল-সংক্রান্ত আরও দুটি সমস্যা জানা দরকার। cron নিজে start হলে @reboot চালু হয়। এটি network ready হওয়ার একই সময় নয়। তাই DNS বা remote host প্রয়োজন এমন job 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>&1

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

systemd timer কখন বেশি উপযোগী

cron একটি কাজ ভালোভাবে করে: নির্দিষ্ট সময়ে একটি কমান্ড চালানো। অন্য প্রায় সব ক্ষেত্রেই এটি সীমিত। একটি timer কোনো redirect ছাড়াই journal-এ লগ রাখে, পরে যাচাই করা যায় এমন exit status দেয়, network-online.target-এর সঙ্গে execution ordering নির্ধারণ করতে পারে, এবং একটি এলোমেলো delay যোগ করতে পারে, যাতে একশোটি সার্ভার একই সেকেন্ডে কাজ শুরু না করে। আপনার job-এর এসব বৈশিষ্ট্যের কোনোটি প্রয়োজন হলে, VPS-এ একটি systemd service ও timer ব্যবহার করা crontab line রক্ষার চেয়ে কম কাজের। Retry behavior-ও সেখানেই নির্ধারণ করা উচিত, কারণ systemd restart policy failure-এর পরে কী হবে তা ঠিক করে; cron এই প্রশ্নের কোনো উত্তর দেয় না।

ছোট কাজগুলোর জন্য cron ব্যবহার করুন। Dependency বা retry policy থাকা যেকোনো কাজ timer-এ স্থানান্তর করুন। একই সার্ভারে দুটিই চালানো যায়, তাই এই migration একবারে সম্পূর্ণ করতেই হবে না।

FAQ

আমার cron job হাতে চালালে কাজ করে, কিন্তু cron থেকে ব্যর্থ হয় কেন?

কারণ আপনার shell এবং cron-এর environment আলাদা। আপনার login shell /etc/profile এবং ~/.bashrc পড়ে, যা PATH, locale এবং আপনার agent variable নির্ধারণ করে। 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-এ নির্ধারিত মিনিটে entry খুঁজুন এবং সেখানে আপনার command-এর নাম আছে কি না পরীক্ষা করুন। কোনো entry না থাকলে cron schedule-টি পায়নি। তাই সঠিক crontab সম্পাদনা করেছেন কি না নিশ্চিত করুন। entry আছে কিন্তু কোনো ফলাফল নেই মানে command শুরু হয়ে বন্ধ হয়ে গেছে। redirect ব্যবহার করে এর output সংরক্ষণ করুন।

crontab-এর ভেতরে date +%Y নষ্ট হয় কেন?

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

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

এটি local mail system-এ যায়। প্রাপক হিসেবে crontab-এর owner অথবা MAILTO-এ নির্ধারিত ঠিকানা ব্যবহৃত হয়। অধিকাংশ VPS image-এ mail transfer agent ইনস্টল করা থাকে না। তাই বার্তাটি বাতিল হয়ে যায় এবং 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 রাখতে চাইলে, query করা যায় এমন exit status প্রয়োজন হলে, network চালু হওয়ার পর job সাজাতে চাইলে, randomized start delay দরকার হলে অথবা failure-এর পরে retry policy চাইলে timer ব্যবহার করুন। একই server-এ দুটিই চালানো যায়। তাই প্রয়োজন অনুযায়ী job একবারে একটি করে স্থানান্তর করতে পারেন।