cron job ஏன் இயங்கவில்லை? 5 முக்கிய காரணங்கள்
உங்கள் cron job இயங்காததற்கான 5 காரணங்கள்: PATH சிக்கல், percent sign, தவறான crontab file, mail-க்குச் செல்லும் output மற்றும் shell சூழல் மாற்றங்களை இதில் விரிவாகக் காணலாம்.
உங்கள் cron job ஏன் இயங்கவில்லை
"ஒருபோதும் இயங்காத" ஒரு cron job, உண்மையில் இயங்கியிருக்கும். அது உங்கள் shell அல்லாத ஒரு சூழலில் இயங்கியிருக்கும், முதல் நொடியிலேயே தோல்வியடைந்திருக்கும், மேலும் அதன் செய்தி நீங்கள் கவனிக்காத ஏதோ ஒரு இடத்திற்குச் சென்றிருக்கும். ஐந்து காரணங்கள் பெரும்பாலான புகார்களுக்கு அடிப்படையாக அமைகின்றன: search path, percent sign, தவறான crontab file, mail-க்குச் சென்ற output, மற்றும் login session-ஐ எதிர்பார்க்கும் script.
cron என்பது crontab கோப்புகளைப் படித்து, குறிப்பிட்ட கால அட்டவணையில் கட்டளைகளைத் தொடங்கும் ஒரு daemon (பின்னணி சேவை) ஆகும். இது உங்கள் .bashrc-ஐப் படிப்பதில்லை, terminal-ஐத் திறப்பதில்லை, login shell-ஐத் தொடங்குவதில்லை, மேலும் ஒரு கட்டளை தோல்வியடையும் போது உங்களுக்குத் தெரிவிப்பதில்லை. கீழே உள்ள ஒவ்வொரு காரணமும் இந்த நான்கு உண்மைகளிலிருந்தே உருவாகின்றன.
இவற்றை வரிசையாகச் சரிபார்க்கவும், எல்லாவற்றிற்கும் அடிப்படையான இந்தக் கேள்வியிலிருந்து தொடங்கவும்: cron உண்மையில் இயங்கியதா? "cron அந்த வேலையைத் தொடங்கவே இல்லை" மற்றும் "வேலை தொடங்கி தோல்வியடைந்தது" ஆகிய இரண்டும் பொதுவான அம்சம் இல்லாத வெவ்வேறு சிக்கல்கள், எனவே முதலில் அதற்குப் பதிலளியுங்கள்.
cron இயங்கியதா?
பல்வேறு distribution குடும்பங்களில் இந்த daemon வெவ்வேறு unit பெயர்களைக் கொண்டுள்ளது. இரண்டையும் சரிபார்த்து, பின் 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 என்று அழைக்கப்படுகிறது. ஒரு குறிப்பிட்ட கணினியில் இவற்றில் ஏதேனும் ஒன்று மட்டுமே இருக்கும் என்பதால், ஏதேனும் ஒரு கட்டளை unknown unit என்று பிழையைக் காட்டுவது இயல்பானது, அது ஒரு குறைபாடு அல்ல.
உங்கள் கணினி பதிவு செய்துள்ள உள்ளீடுகளை வாசிக்கவும். வழிகாட்டி ஒன்றிலிருந்து நகலெடுக்கப்பட்ட வரியைத் தேட வேண்டாம், ஏனெனில் cron செயலாக்கங்கள் மற்றும் logging அமைப்புகளுக்கு இடையே வாசகங்கள் மாறுபடும். நீங்கள் இரண்டு விஷயங்களை மட்டுமே சரிபார்க்கிறீர்கள்: உங்கள் அட்டவணையில் உள்ள நிமிடத்தில் ஒரு உள்ளீடு உள்ளதா, மற்றும் அந்த உள்ளீடு உங்கள் கட்டளையைக் குறிப்பிடுகிறதா என்பதுதான். உங்கள் கட்டளையைக் குறிப்பிடும் ஒரு உள்ளீடு இருந்தால், cron அதன் பணியைச் செய்துவிட்டது என்றும், பிழை அந்த கட்டளைக்குள் உள்ளது என்றும் பொருள். எந்த உள்ளீடும் இல்லை என்றால், cron-இடம் உங்கள் அட்டவணை இல்லை என்று பொருள், இது கீழே உள்ள 3-வது காரணத்தைக் குறிக்கும்.
சில images, cron செய்திகளை journal-க்கு பதிலாக rsyslog வழியாக ஒரு கோப்பிற்கு அனுப்புகின்றன. /var/log-ல் cron அல்லது syslog பெயரில் உள்ள கோப்பைத் தேடி, அதன் முடிவைப் படிக்கவும்.
ls -l /var/log
sudo tail -n 50 /var/log/syslogunit அல்லது log ஆகிய இரண்டுமே இல்லை என்றால், cron நிறுவப்படாமல் இருக்கலாம். மிகச்சிறிய 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 மற்றும் அந்த கோப்புகள் குறிப்பிடும் பிற கோப்புகளிலிருந்து உருவாக்குகிறது. cron job இயங்கும்போது இவை எதுவும் செயல்படுவதில்லை. cron தனது சொந்த சிறிய சூழலுடன் கட்டளையைத் தொடங்குவதால், நிலையான கணினி கோப்பகங்களுக்கு வெளியே இருக்கும் நிரல்களை அதனால் கண்டறிய முடியாது. /usr/local/bin, /opt, language version manager, Python virtual environment அல்லது Go workspace ஆகியவற்றின் கீழ் உள்ள அனைத்தும் இதில் அடங்கும். முதல் வரியிலேயே job தோல்வியடையும், மேலும் எந்த shell அதை இயக்கியதோ அதற்கேற்ப "not found" என்ற பிழைச் செய்தியை shell எழுதும்.
உங்கள் job பயன்படுத்தும் ஒவ்வொரு கட்டளையின் உண்மையான பாதையைக் கண்டறியவும்.
command -v docker
command -v node
readlink -f "$(command -v node)"பிறகு, அந்த முழுமையான பாதைகளை (absolute paths) job-ல் எழுதவும் அல்லது 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-ல் மட்டும் இருக்கும் எதையும் நீக்கிவிடவும். இதில் ஒரு விதி முக்கியமானது: இந்த assignment வரிகளில் cron மாறிகளை (variables) விரிவுபடுத்தாது (expand). PATH=$PATH:/usr/local/bin என்பது $PATH:/usr/local/bin என்ற எழுத்துக்களை அப்படியே சேமிக்கும், எனவே அந்த job-ன் தேடல் பாதையில் எந்தப் பயன்பாட்டு கோப்பகமும் இருக்காது. முழுப் பட்டியலையும் விரிவாக எழுதவும்.
ஒரு version manager-க்கு PATH மட்டும் போதாது. nvm, pyenv, rbenv மற்றும் asdf ஆகியவை உங்கள் .bashrc-லிருந்து ஒரு shell function அல்லது shims கோப்பகத்தை நிறுவுகின்றன, ஆனால் cron job அந்த கோப்பை ஒருபோதும் வாசிப்பதில்லை. versioned binary-ஐ அதன் முழுமையான பாதையைக் கொண்டு அழைக்கவும் அல்லது உங்கள் script-ன் முதல் வரியாக manager-ன் init script-ஐ source செய்யவும்.
காரணம் 2: சதவீதக் குறியீடு (percent sign) உங்கள் கட்டளையை முடித்துவிடுகிறது
crontab-ன் கட்டளைப் பகுதியில், % என்பது சாதாரணமான குறியீடு அல்ல. எஸ்கேப் (unescaped) செய்யப்படாத முதல் % கட்டளையை முடித்துவிடுகிறது. அதற்குப் பிறகு வரும் அனைத்தும் standard input-ஆக கட்டளைக்கு அனுப்பப்படும், மேலும் ஒவ்வொரு கூடுதல் %-ம் புதிய வரியாக (newline) மாறும். இது ஒரு நிரலுக்குச் சிறிய உள்ளீட்டை வழங்க cron-ல் உள்ள ஒரு வசதியாகும், இதனால்தான் தேதி குறிப்பிடப்பட்ட கோப்புப் பெயர்கள் (date-stamped filename) பெரும்பாலும் crontab-ல் பிழையை ஏற்படுத்துகின்றன.
0 3 * * * /usr/bin/tar -czf /srv/backups/site-$(date +%F).tar.gz /srv/site என்று எழுதினால், tar கட்டளை வடிவமைக்கப்பட்ட தேதியைப் பார்க்காது. cron வரியை முதல் %-ல் துண்டித்துவிடுகிறது, எனவே shell ஒரு முழுமையற்ற கட்டளை மாற்றத்தைப் (command substitution) பெறுகிறது, மேலும் வரியின் மீதமுள்ள பகுதி standard input-ஆகச் செல்கிறது. ஒவ்வொரு சதவீதக் குறியீட்டையும் ஒரு backslash கொண்டு எஸ்கேப் செய்யவும்.
0 3 * * * /usr/bin/tar -czf /srv/backups/site-$(date +\%F).tar.gz /srv/siteஇரண்டு அடுக்குகள் அந்த ஒரு வரியை வரிசையாகப் படிக்கின்றன. \% என்பது ஒரு cron விதி, இது எதையும் தொடங்குவதற்கு முன்பு cron-ஆல் செயல்படுத்தப்படுகிறது. $(date +\%F) என்பது கட்டளை மாற்றம், இது cron தொடங்கும் shell-ஆல் பின்னர் செயல்படுத்தப்படுகிறது. எந்த அடுக்கு எந்தக் குறியீட்டைக் கையாள்கிறது என்பதை அறிவதே இதற்கான தீர்வாகும்.
crontab-ல் தர்க்கங்களை (logic) தவிர்ப்பதே பாதுகாப்பான பழக்கமாகும். அவற்றை ஒரு script-ல் வைக்கவும், அங்கு சதவீதக் குறியீட்டிற்குச் சிறப்பு அர்த்தம் இல்லை.
#!/bin/bash
set -euo pipefail
stamp="$(date +%F)"
tar -czf "/srv/backups/site-${stamp}.tar.gz" /srv/siteஅப்போது crontab வரியில் ஒரு பாதை (path) மற்றும் ஒரு redirect மட்டுமே இருக்கும். ஒரே பார்வையில் புரிந்துகொள்ளக்கூடிய crontab-ஐ பிழைத்திருத்தம் (debug) செய்வது எளிது.
காரணம் 3: நீங்கள் எந்த crontab-ஐத் திருத்தினீர்கள்?
ஒரே ஒரு crontab மட்டும் கிடையாது. வெவ்வேறு உரிமையாளர்கள் மற்றும் வெவ்வேறு புலங்களைக் (field counts) கொண்ட பல கோப்புகள் உள்ளன. தவறான கோப்பில் எழுதப்படும் ஒரு பணி (job) கண்ணுக்குத் தெரியாமல் போய்விடும்.
crontab -eகட்டளையை இயக்கும் பயனரின் crontab-ஐத் திருத்தும்.sudo crontab -eroot பயனரின் crontab-ஐத் திருத்தும். ஒரே server-ஐப் பிழைத்திருத்தம் செய்யும் இருவர், பெரும்பாலும் இரண்டு வெவ்வேறு கோப்புகளைப் பார்ப்பார்கள்.sudo crontab -l -u deployமற்றொரு பயனரின் crontab-ஐப் பட்டியலிடும். பணி இயங்க வேண்டிய கணக்கிற்கு உண்மையில் என்ன நிறுவப்பட்டுள்ளது என்பதை உறுதிப்படுத்த இதுவே வழி./etc/crontabமற்றும்/etc/cron.d-ல் உள்ள ஒவ்வொரு கோப்பிலும் கால அட்டவணைக்கும் கட்டளைக்கும் இடையில் ஒரு கூடுதல் புலம் (field) இருக்கும்: அது எந்தப் பயனராக இயங்க வேண்டும் என்பதைக் குறிக்கும். ஐந்து புலங்களைக் கொண்ட user crontab வரியை/etc/cron.d-ல் நகலெடுத்து ஒட்டினால், உங்கள் கட்டளையின் முதல் சொல் பயனர் பெயராகக் கருதப்படும்./etc/cron.d-ல் உள்ள கோப்புகள் எழுத்துக்கள், எண்கள், அடிக்கோடுகள் (underscores) மற்றும் ஹைபன்களைக் கொண்டு பெயரிடப்பட வேண்டும்.backup.shஅல்லதுsite.confஎன்று பெயரிடப்பட்ட கோப்புகள், அவற்றின் பெயரின் காரணமாகவே தவிர்க்கப்படும். அதைbackupஎன மறுபெயரிட்டு, உங்கள் log-ஐ மீண்டும் சரிபார்க்கவும்./etc/cron.d-ல் உள்ள கோப்புகள் root உரிமையில் இருக்க வேண்டும், மேலும் group அல்லது பிற பயனர்கள் எழுதும் உரிமை (writable) கொண்டிருக்கக்கூடாது.ls -l /etc/cron.dஇந்த இரண்டு உண்மைகளையும் ஒரே நேரத்தில் காட்டும்./etc/cron.dailyமற்றும் அதன் துணை அடைவுகளில் இடப்படும் ஸ்கிரிப்ட்கள் அதே பெயரிடும் விதியைப் பின்பற்ற வேண்டும், மேலும் அவற்றுக்கு execute bit இருக்க வேண்டும். execute bit விடுபட்டால், அது எந்தத் தகவலும் இன்றி தவிர்க்கப்படும்./etc/cron.allowமற்றும்/etc/cron.denyஆகியவை யாருக்கு crontab-ஐ நிறுவ அனுமதி உண்டு என்பதைத் தீர்மானிக்கின்றன. உங்கள் server-ல் இவை இருந்தால், உங்கள் பயனருக்கு அனுமதி உண்டு என்று கருதுவதற்கு முன் அவற்றைப் படிக்கவும்.
spool கோப்பை நேரடியாகத் திருத்துவதற்குப் பதிலாக, crontab கட்டளையைப் பயன்படுத்தி user crontab-ஐ நிறுவவும். ஏனெனில் crontab கோப்பை நிறுவும் முன் அதைச் சரிபார்க்கும் (parse). நீங்கள் சேமிக்கும்போது, அந்தக் கட்டளை என்ன வெளியீட்டைத் தருகிறது என்று கவனிக்கவும். அது கோப்பை நிராகரித்தால், முந்தைய பதிப்பே செயல்பாட்டில் இருக்கும், உங்கள் மாற்றம் நடைமுறைக்கு வராது. இது cron உங்களைப் புறக்கணிப்பது போலத் தோன்றும்.
உரிமையாளரே அனுமதிகளையும் (permissions) தீர்மானிக்கிறார். root-ன் crontab-ல் உள்ள ஒரு பணி, root-க்குச் சொந்தமான கோப்புகளை உருவாக்கும்; அவற்றை வாசிக்கும் application-ஆல் அவற்றை எழுத முடியாமல் போகலாம். சாதாரண பயனரின் crontab-ல் உள்ள ஒரு பணியால் root-க்கு மட்டுமே உரிய அடைவை வாசிக்க முடியாது. பணியின் தன்மைக்கு ஏற்ப உரிமையாளரைத் தேர்வு செய்யவும்: application பராமரிப்புப் பணிகள் அந்த application-ன் சொந்தக் கணக்கிலேயே இருக்க வேண்டும். இதனால்தான் WordPress wp-cron-க்கு பதிலாக system cron job-ஐப் பயன்படுத்துவது பரிந்துரைக்கப்படுகிறது. உங்கள் பணி உருவாக்கும் கோப்புகளின் mode, அது பெறும் umask-லிருந்து வருகிறது. இது உங்கள் shell-ன் umask-லிருந்து மாறுபடலாம், எனவே umask எவ்வாறு கோப்பு அனுமதிகளை அமைக்கிறது என்பதைப் படிப்பது பயனுள்ளதாக இருக்கும். ஒரு பணியின் வெளியீடு வாசிக்க முடியாத நிலையில் இருந்தால் இதுவே காரணமாக இருக்கலாம்.
காரணம் 4: வெளியீடு யாரும் படிக்காத மின்னஞ்சலுக்குச் சென்றது
ஒரு job எழுதும் standard output மற்றும் standard error ஆகிய அனைத்தையும் cron சேகரிக்கும். அந்த job ஏதேனும் தகவலை வெளியிட்டால், cron அதை உள்ளூர் மின்னஞ்சல் முறைமைக்கு (local mail system) அனுப்பிவிடும்; இது crontab-ன் உரிமையாளருக்கோ அல்லது MAILTO-ல் குறிப்பிடப்பட்டுள்ளவருக்கோ அனுப்பப்படும். ஒரு அடிப்படை VPS-ல் பொதுவாக MTA (mail transfer agent) நிறுவப்பட்டிருக்காது, எனவே அந்த மின்னஞ்சல் எங்கும் சேராது. உங்கள் பிழை ஒரு கணம் தோன்றி, பின் மறைந்துவிடும். ஒரு broken job அமைதியாக இருப்பதற்கு இதுவே முழுமையான காரணம்.
அதற்குப் பதிலாக, வெளியீட்டை நீங்கள் கண்காணிக்கும் ஒரு கோப்பிற்கு (file) அனுப்புங்கள்.
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 அதன் பழைய இடத்திற்கே செல்லும்; நீங்கள் தேடும் பிழை அந்த கோப்பிற்குச் செல்லவே செல்லாது.
Journal என்பது மற்றொரு சிறந்த இலக்காகும். logger என்பது நீங்கள் தேர்ந்தெடுக்கும் ஒரு tag-ன் கீழ் syslog-ல் தகவலை எழுதும்.
0 3 * * * /usr/local/sbin/backup-site.sh 2>&1 | logger -t backup-siteஇதை journalctl -t backup-site மூலம் வாசிக்கலாம். இது cron பதிவுகளுக்கு அருகிலேயே அந்த job-ன் வெளியீட்டையும் வைத்திருப்பதால், காலவரிசையைப் புரிந்துகொள்வது எளிது. எந்த பயனர் எந்த கட்டளையை இயக்கினார் என்பதற்கான பதிவு உங்களுக்குத் தேவைப்பட்டால், அது ஒரு தனி முறைமை; உங்கள் server-ல் பயனர் கட்டளைகளை தணிக்கை செய்தல் பகுதியில் அதைப் பார்க்கலாம்.
Crontab-ன் தொடக்கத்தில் MAILTO=""-ஐச் சேர்ப்பது, அதற்கு கீழே உள்ள job-களுக்கான மின்னஞ்சல் அறிவிப்புகளை நிறுத்திவிடும். MAILTO-ஐ ஒரு சரியான மின்னஞ்சல் முகவரிக்கு அமைப்பது, ஒரு செயல்படும் MTA இருந்தால் மட்டுமே உதவும்; எனவே, அதை நம்புவதற்கு முன் மின்னஞ்சல் server-ஐ விட்டு வெளியேறுகிறதா என்பதை உறுதிப்படுத்திக் கொள்ளுங்கள்.
பிழைத்திருத்தம் (debugging) செய்யும் போது ஒரு விதி: ஒருபோதும் > /dev/null 2>&1-ஐச் சேர்க்காதீர்கள். இது ஒவ்வொரு crontab-லும் மிகவும் பொதுவாகப் பயன்படுத்தப்படும் வரியாகும், ஆனால் இது உங்களிடம் உள்ள ஒரே ஆதாரத்தை அழித்துவிடும். job சரியாகச் செயல்படத் தொடங்கிய பிறகு, வேண்டுமென்றால் இதை மீண்டும் சேர்த்துக்கொள்ளலாம்.
காரணம் 5: cron வழங்கும் சூழலில் script-க்குத் தேவையானவை இல்லை
கட்டளை கண்டறியப்பட்டு அதன் வெளியீடு பெறப்பட்ட பிறகு, உங்கள் session-ல் இயல்பாகக் கிடைக்கும் பிற வசதிகள் இதில் இருக்காது.
- shell என்பது bash-ஆக இல்லாமல் இருக்கலாம்.
ls -l /bin/shமூலம் சரிபார்க்கவும். Debian மற்றும் Ubuntu-வில் இது dash-ஐக் குறிக்கும், எனவே double bracket test, arrays மற்றும்sourceஆகியவை syntax error-ஐ ஏற்படுத்தும். script-ன் தொடக்கத்தில்#!/bin/bashவரியைச் சேர்த்து script-ஐ இயக்கவும் அல்லது crontab-ன் உச்சியில்SHELL-ஐ அமைக்கவும். - நீங்கள் இருந்த working directory-ல் இது இயங்காது. எல்லா இடங்களிலும் absolute paths-ஐப் பயன்படுத்தவும் அல்லது script-ன் முதல் வரியில் அந்த directory-க்கு
cdசெய்யவும். "நான் நேரடியாக இயக்கும்போது வேலை செய்கிறது" என்று சொல்லப்படும் பணிகளுக்கு, relative path-ஐப் பயன்படுத்துவதே பொதுவான காரணமாகும். - locale உங்கள் session-ஐப் போல இருக்காது. தேதியையோ அல்லது எண்ணையோ வடிவமைக்கும் அல்லது உரையை வரிசைப்படுத்தும் எந்தவொரு செயலும், வெவ்வேறு
LANGசூழலில் மாறுபட்ட வெளியீட்டைத் தரலாம். அடுத்தடுத்த நிலைகளில் அந்த வெளியீடு பகுப்பாய்வு செய்யப்பட்டால், எதார்த்தத்தை நம்பியிருக்காமல் script-லேயே locale-ஐ அமைக்கவும். - TTY (terminal) இருக்காது. உறுதிப்படுத்தல் கேட்கும், editor-ஐத் திறக்கும் அல்லது progress bar-ஐக் காட்டும் கட்டளைகள் முடங்கலாம் அல்லது வெளியேறலாம். அந்த tool வழங்கும் non-interactive flag-ஐச் சேர்க்கவும்.
- SSH agent இருக்காது. cron-ன் சூழலில்
SSH_AUTH_SOCKஇருக்காது, எனவே உங்கள் agent loaded-ஆக இருந்ததால் வேலை செய்தsshஅல்லதுrsyncகட்டளைகள் இப்போது authentication தோல்வியடையும். அந்தப் பணிக்குச் சொந்தமான user-க்கு உரிய தனிப்பட்ட key-ஐ வழங்கவும். - user session bus இருக்காது, எனவே
XDG_RUNTIME_DIRஅமைக்கப்படாத வரை cron job-லிருந்துsystemctl --userதோல்வியடையும். இதற்கு system unit-ஐப் பயன்படுத்துவதே சிறந்த தீர்வாகும்.
Fedora, Rocky மற்றும் Alma ஆகியவற்றில் மற்றொரு சந்தேகத்திற்குரிய அம்சம் உள்ளது. SELinux, cron jobs-ஐக் கட்டுப்படுத்துகிறது. எனவே, கோப்பு அனுமதிகள் (file permissions) சரியாக இருந்தாலும், எதிர்பாராத label கொண்ட பாதையை அணுகும் பணி தடுக்கப்படும். sudo ausearch -m avc -ts recent மூலம் தடைகளைச் சரிபார்க்கவும். எதையும் முடக்கும் முன் SELinux basics for a server என்பதைப் படிக்கவும்.
cron-ன் சூழலை வெளிப்படுத்தும் ஒரு நிமிட ஆய்வு
cron-ன் சூழலில் என்னென்ன மாறிகள் உள்ளன என்பதை ஊகிப்பதை நிறுத்திவிட்டு, அதை நேரடியாகப் படியுங்கள். அனைத்து விவரங்களையும் ஒரு கோப்பில் பதிக்கும் script ஒன்றை எழுதி, அதை ஒவ்வொரு நிமிடமும் இயங்குமாறு அட்டவணைப்படுத்தி, சிறிது நேரம் காத்திருந்து, பின் அந்தக் கோப்பைப் படியுங்கள்.
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 paths) குறிப்பிட்டு ஒரு வரியைச் சேர்க்கவும்.
* * * * * /home/deploy/cron-probe.sh >> /home/deploy/cron-probe.log 2>&1ஒரு நிமிடம் காத்திருந்து, /home/deploy/cron-probe.log கோப்பைப் படித்து, உங்கள் shell-ல் அதே கட்டளைகளை இயக்கும்போது கிடைக்கும் முடிவுகளுடன் ஒப்பிட்டுப் பாருங்கள். PATH வரி, பணி நடக்கும் கோப்பகம் (working directory) மற்றும் locale ஆகியவையே பெரும்பாலும் தோல்விக்கான காரணத்தைத் தெளிவுபடுத்திவிடும். இந்த அமைப்பில் இரண்டு விவரங்களைக் கவனத்தில் கொள்ளவும்: script-க்குள் இருக்கும் percent signs-க்கு cron-ன் விதிகள் பொருந்தாது, மேலும் log கோப்பு எழுதப்படும் பாதை அந்த user-க்கு எழுதும் அனுமதி (write permission) கொண்டதாக இருக்க வேண்டும்.
விடை கிடைத்தவுடன் அந்த crontab வரியை நீக்கிவிடவும். ஒவ்வொரு நிமிடமும் இயங்கி ஒரு கோப்பில் தகவல்களைச் சேர்க்கும் பணி, சிறிய disk-ஐ விரைவாக நிரப்பிவிடும், அதுவும் அமைதியாகவே நடக்கும்.
நீங்கள் குறிப்பிட்ட கால அட்டவணை இதுதானா?
ஒரு பயனர் crontab வரியானது ஐந்து புலங்களைக் கொண்டது: நிமிடம், மணிநேரம், மாதத்தின் நாள், மாதம், வாரத்தின் நாள். இதில் இரண்டு புலங்கள் பயனர்களை வியக்க வைக்கும் வகையில் ஒன்றோடொன்று செயல்படுகின்றன.
மாதத்தின் நாள் மற்றும் வாரத்தின் நாள் ஆகிய இரண்டுமே * என இல்லாமல் கட்டுப்படுத்தப்பட்டிருந்தால், ஏதேனும் ஒரு புலம் பொருந்தும்போதே cron அந்த வேலையை இயக்கும். 0 0 13 * 5 என்பது "13-ஆம் தேதி வெள்ளிக்கிழமை" என்று பொருளல்ல. இது ஒவ்வொரு மாதத்தின் 13-ஆம் தேதியன்றும் நள்ளிரவிலும், ஒவ்வொரு வெள்ளிக்கிழமையன்றும் நள்ளிரவிலும் இயங்கும். ஒரு குறிப்பிட்ட நாளை மட்டும் பெற, இரண்டு புலங்களில் ஒன்றை * என விட்டுவிட்டு, மற்றொன்றை script-க்குள் சோதிக்கவும்.
cron கணினியின் timezone-ஐப் பயன்படுத்துகிறது. பல VPS images UTC (coordinated universal time)-ல் அமைக்கப்பட்டு வழங்கப்படுகின்றன. எனவே, நீங்கள் 03:00 மணிக்குத் திட்டமிடும் வேலை 03:00 UTC-ல் இயங்கும், இது உங்கள் உள்ளூர் நேரப்படி மதிய நேரமாக இருக்கலாம். timedatectl உங்கள் கணினி தற்போது பயன்படுத்தும் நேரத்தைக் காட்டும். உங்கள் மடிக்கணினியின் நேரத்தோடு இது ஒத்துப்போகும் என்று கருதாமல், உங்கள் server-ன் நேரத்தைச் சரிபார்க்கவும்.
கால அட்டவணையில் கவனிக்க வேண்டிய மேலும் இரண்டு சிக்கல்கள் உள்ளன. @reboot என்பது cron தொடங்கும் போது இயங்கும், இது network தயாராக இருக்கும் தருணமும் அல்ல. எனவே, DNS அல்லது remote host தேவைப்படும் ஒரு வேலை boot நேரத்தில் தோல்வியடைந்து, பின்னர் கைமுறையாக இயக்கும்போது வெற்றிபெறலாம். மேலும், ஒரு மெதுவான வேலை இயங்கிக்கொண்டிருக்கும்போதே, அதன் அடுத்த நகல் தொடங்குவதைத் தடுக்க எதுவுமில்லை. எனவே, அதை ஒரு 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 ஏற்கனவே பயன்பாட்டில் இருந்தால் உடனடியாக வேலையை நிறுத்திவிடும், இதனால் ஒரே வேலை பலமுறை ஒன்றன் மேல் ஒன்றாக இயங்குவது தவிர்க்கப்படும்.
systemd timer எப்போது சிறந்த கருவியாகிறது
cron ஒரு குறிப்பிட்ட நேரத்தில் ஒரு கட்டளையை இயக்குவதற்கு மட்டுமே சிறந்தது. மற்ற அனைத்து அம்சங்களிலும் இது பலவீனமானது. ஒரு timer, எந்தவிதமான redirect-ம் இன்றி journal-ஐ வழங்குகிறது, நீங்கள் பின்னர் சரிபார்க்கக்கூடிய exit status-ஐத் தருகிறது, network-online.target-க்கு எதிரான வரிசைப்படுத்தலை (ordering) அனுமதிக்கிறது, மேலும் நூற்றுக்கணக்கான server-கள் ஒரே நொடியில் தொடங்காமல் இருக்க randomized delay-ஐ வழங்குகிறது. உங்கள் பணிக்கு இவை ஏதேனும் தேவைப்பட்டால், crontab வரியைப் பராமரிப்பதை விட VPS-ல் systemd service மற்றும் timer-ஐ அமைப்பது குறைவான வேலையே. service பகுதியை எழுதும் போது, cron ஒருபோதும் கேட்காத ஒரு கேள்வியை இது எழுப்புகிறது: அதாவது, பணி உண்மையில் தொடங்கிவிட்டது என்பதை unit எவ்வாறு அறியும் என்பதுதான். எனவே, முதலில் simple, forking மற்றும் notify unit-களுக்கு Type= எதைக் குறிக்கிறது என்பதைப் படிக்கவும். ஏனெனில், default type-ன் கீழ் தன்னைத்தானே daemonize செய்துகொள்ளும் ஒரு script, பின்னணியில் ஏதுமின்றி unit-ஐ active நிலையில் இருப்பது போலக் காட்டும். Retry செயல்பாடுகளும் இதில் அடங்கும், ஏனெனில் systemd restart கொள்கைகள் தோல்விக்குப் பிறகு என்ன நடக்க வேண்டும் என்பதைத் தீர்மானிக்கின்றன, ஆனால் cron-னிடம் இந்தக் கேள்விக்கு எந்த பதிலும் இல்லை.
சிறிய பணிகளுக்கு cron-ஐத் தொடர்ந்து பயன்படுத்துங்கள். dependencies அல்லது retry policy கொண்ட எதையும் timer-க்கு மாற்றுங்கள். இவை இரண்டையும் ஒரே server-ல் இயக்க முடியும் என்பதால், இந்த மாற்றத்தை ஒரே நேரத்தில் முடிக்க வேண்டிய அவசியமில்லை.
FAQ
எனது cron job நேரடியாக இயக்கும்போது வேலை செய்கிறது, ஆனால் cron மூலம் இயக்கும்போது ஏன் தோல்வியடைகிறது?
ஏனெனில் உங்கள் shell மற்றும் cron-ன் environment மாறுபட்டவை. உங்கள் login shell /etc/profile மற்றும் ~/.bashrc ஆகியவற்றை வாசிக்கும்; இவை PATH, locale மற்றும் உங்கள் agent variables ஆகியவற்றை அமைக்கும். cron இந்த அமைப்புகள் எதுவுமின்றி, வேறுபட்ட working directory-லிருந்து, சில நேரங்களில் வேறுபட்ட shell-ஐப் பயன்படுத்தி கட்டளையைத் தொடங்கும். ஒவ்வொரு கட்டளைக்கும் absolute paths-ஐப் பயன்படுத்தவும், crontab-ன் மேலேயோ அல்லது script-க்கு உள்ளேயோ உங்களுக்குத் தேவையானவற்றை அமைக்கவும். ஒரு நிமிடத்திற்கு ஒருமுறை இயங்கும் probe job-ஐ உருவாக்கி, env | sort, pwd மற்றும் id ஆகியவற்றின் வெளியீட்டை ஒரு log file-ல் சேமிக்கவும். இதன் மூலம் cron-ன் உண்மையான environment-ஐ ஊகிப்பதற்குப் பதிலாக நேரடியாகப் பார்க்க முடியும்.
cron எனது வேலையைச் சரியாகச் செய்ததா என்பதை எப்படிச் சரிபார்ப்பது?
daemon-ன் log-ஐ வாசிக்கவும். Debian மற்றும் Ubuntu-வில் journalctl -u cron-ஐயும், Fedora, Rocky மற்றும் Alma-வில் journalctl -u crond-ஐயும் பயன்படுத்தவும்; சில images செய்திகளை rsyslog வழியாக /var/log-க்குக் கீழே உள்ள ஒரு கோப்பிற்கு அனுப்பும். நீங்கள் குறிப்பிட்ட நேரத்தில் ஒரு entry உள்ளதா என்று பார்க்கவும், அது உங்கள் கட்டளையைக் குறிப்பிடுகிறதா என்று சரிபார்க்கவும். entry இல்லை என்றால், cron-க்கு அந்த schedule கிடைக்கவில்லை என்று அர்த்தம், எனவே சரியான crontab-ஐத் திருத்தினீர்களா என்பதை உறுதிப்படுத்தவும். entry இருந்து எந்த முடிவும் இல்லை என்றால், கட்டளை தொடங்கி நின்றுவிட்டது என்று அர்த்தம், எனவே அதன் வெளியீட்டை ஒரு redirect மூலம் சேமிக்கவும்.
crontab-க்குள் ஏன் date +%Y வேலை செய்யவில்லை?
command field-ல் %-ஐ cron சிறப்பு குறியீடாகக் கருதுகிறது. escape செய்யப்படாத முதல் % கட்டளையை முடித்துவிடும், அதற்குப் பின் உள்ளவை அனைத்தும் standard input-ஆக அந்தக் கட்டளைக்கு அனுப்பப்படும், மேலும் ஒவ்வொரு கூடுதல் %-ம் புதிய வரியாக (newline) மாறும். எனவே, date-formatted filename நீங்கள் எழுதிய நிரலுக்குச் சென்றடையாது. ஒவ்வொரு percent குறியீட்டையும் \% என escape செய்யவும், அல்லது கட்டளையை ஒரு script-க்குள் நகர்த்திவிட்டு cron-லிருந்து அந்த script-ஐ அழைக்கவும், ஏனெனில் script-க்குள் percent குறியீட்டிற்குச் சிறப்பு அர்த்தம் இல்லை.
எனது cron job-ன் வெளியீடு எங்கே செல்கிறது?
இது உள்ளூர் mail system-க்கு, crontab-ன் உரிமையாளருக்கோ அல்லது MAILTO-ல் குறிப்பிடப்பட்டுள்ளவருக்கோ அனுப்பப்படும். பெரும்பாலான VPS images-ல் mail transfer agent நிறுவப்பட்டிருக்காது, எனவே செய்தி நிராகரிக்கப்படும் மற்றும் job அமைதியாக இருப்பது போலத் தோன்றும். வெளியீட்டை >> /path/to/log 2>&1 மூலம் ஒரு கோப்பிற்கு redirect செய்யவும், standard error-ஐ standard output-ஐத் தொடர்ந்து வைக்க அந்த வரிசையைப் பின்பற்றவும், அல்லது logger -t myjob வழியாக pipe செய்து journalctl -t myjob மூலம் வாசிக்கவும். நீங்கள் debugging செய்துகொண்டிருக்கும்போது > /dev/null 2>&1-ஐப் பயன்படுத்த வேண்டாம்.
நான் cron-ஐப் பயன்படுத்த வேண்டுமா அல்லது systemd timer-ஐப் பயன்படுத்த வேண்டுமா?
குறிப்பிட்ட நேரத்தில் இயங்கும் எளிய கட்டளைகளுக்கு cron-ஐப் பயன்படுத்தவும், குறிப்பாக systemd இல்லாத machine-க்கு மாற்ற வேண்டிய தேவை இருந்தால் இதைப் பயன்படுத்தவும். வெளியீட்டை redirect செய்யாமல் நேரடியாக journal-ல் பெற, exit status-ஐ வினவ, network தயாரான பிறகு இயக்க, சீரற்ற தொடக்க தாமதம் (randomized start delay) அல்லது தோல்விக்குப் பிறகு மீண்டும் முயற்சிக்கும் கொள்கை (retry policy) தேவைப்படும்போது timer-ஐப் பயன்படுத்தவும். இரண்டையும் ஒரே server-ல் இயக்க முடியும், எனவே ஒவ்வொரு job-ன் தேவைக்கேற்ப அவற்றை ஒவ்வொன்றாக மாற்றிக்கொள்ளலாம்.