உங்கள் Cron Job ஏன் இயங்கவில்லை? 5 முக்கிய காரணங்கள்
உங்கள் Cron Job இயங்காததற்கான 5 பொதுவான காரணங்கள் இங்கே உள்ளன. PATH பிழைகள், percent sign, தவறான crontab கோப்பு மற்றும் mail output சிக்கல்களை எவ்வாறு சரிசெய்வது என்பதை அறிக.
உங்கள் 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 இயங்கியதா?
பல்வேறு Linux விநியோகங்களில் இந்த 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 implementations மற்றும் 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 நிறுவப்படாமல் இருக்கலாம். மிகச்சிறிய (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 மற்றும் அந்த கோப்புகள் குறிப்பிடும் பிற கோப்புகளிலிருந்து உருவாக்குகிறது. 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-க்கு வெறும் பாதை மட்டும் போதாது. nvm, pyenv, rbenv மற்றும் asdf ஆகியவை உங்கள் .bashrc-லிருந்து ஒரு shell function அல்லது shims கோப்பகத்தை நிறுவுகின்றன, ஆனால் cron job அந்த கோப்பை ஒருபோதும் வாசிப்பதில்லை. versioned binary-ஐ அதன் முழுமையான பாதையைக் கொண்டு அழைக்கவும் அல்லது உங்கள் script-ன் முதல் வரியாக manager-ன் init script-ஐ source செய்யவும்.
காரணம் 2: சதவீதக் குறியீடு உங்கள் கட்டளையை முடித்துவிடுகிறது
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-ல் வைக்காமல் தவிர்ப்பதே பாதுகாப்பான பழக்கமாகும். அவற்றை ஒரு script-ல் வைக்கவும், அங்கு சதவீதக் குறியீட்டிற்குச் சிறப்பு அர்த்தம் இல்லை.
#!/bin/bash
set -euo pipefail
stamp="$(date +%F)"
tar -czf "/srv/backups/site-${stamp}.tar.gz" /srv/siteஅப்போது crontab வரியில் ஒரு பாதை (path) மற்றும் redirect மட்டுமே இருக்கும். ஒரே பார்வையில் புரிந்துகொள்ளக்கூடிய crontab-ல் பிழைத்திருத்தம் செய்வது எளிது.
காரணம் 3: நீங்கள் எந்த crontab-ஐத் திருத்தினீர்கள்?
ஒரே ஒரு crontab மட்டும் இருப்பதில்லை. வெவ்வேறு உரிமையாளர்கள் மற்றும் வெவ்வேறு புலங்களைக் (field counts) கொண்ட பல கோப்புகள் உள்ளன; தவறான கோப்பில் எழுதப்படும் பணி (job) கண்ணுக்குத் தெரியாமல் போய்விடும்.
crontab -eகட்டளையை இயக்கும் பயனரின் crontab-ஐத் திருத்துகிறது.sudo crontab -eroot-ன் crontab-ஐத் திருத்துகிறது. ஒரே server-ஐ debug செய்யும் இருவர், பெரும்பாலும் இரண்டு வெவ்வேறு கோப்புகளைப் பார்த்துக்கொண்டிருப்பார்கள்.sudo crontab -l -u deployமற்றொரு பயனரின் crontab-ஐப் பட்டியலிடுகிறது; ஒரு பணி எந்தக் கணக்கின் கீழ் இயங்க வேண்டுமோ, அதில் உண்மையில் என்ன நிறுவப்பட்டுள்ளது என்பதை உறுதிப்படுத்த இதுவே வழி./etc/crontabமற்றும்/etc/cron.d-ல் உள்ள ஒவ்வொரு கோப்பிலும், கால அட்டவணைக்கும் (schedule) கட்டளைக்கும் இடையில் ஒரு கூடுதல் புலம் (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மற்றும் அதன் துணை அடைவுகளில் இடப்படும் scripts, அதே பெயரிடும் விதியைப் பின்பற்ற வேண்டும்; மேலும் அவற்றுக்கு 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-க்கு மட்டுமே உரிய directory-ஐ வாசிக்க முடியாது. பணியின் தன்மைக்கு ஏற்ப உரிமையாளரைத் தேர்வு செய்யவும்: 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) நிறுவப்பட்டிருக்காது, எனவே அந்த மின்னஞ்சல் எங்கும் சேராது. உங்கள் பிழை ஒரு கணம் நிகழ்ந்து, பின் மறைந்துவிடும். ஒரு 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 மூலம் வாசிக்கலாம். இது job-ன் வெளியீட்டை cron பதிவுகளுக்கு அருகிலேயே வைத்திருப்பதால், காலவரிசையைப் பின்பற்றுவது எளிது. சர்வரில் எந்த பயனர் எந்த கட்டளையை இயக்கினார் என்பதற்கான பதிவு தேவைப்பட்டால், அது ஒரு தனி அமைப்பு; உங்கள் சர்வரில் பயனர் கட்டளைகளை தணிக்கை செய்தல் (auditing user commands on your server) பகுதியில் அதைப் பார்க்கலாம்.
Crontab-ன் தொடக்கத்தில் MAILTO="" என்று குறிப்பிடுவது, அதற்கு கீழே உள்ள job-களுக்கான மின்னஞ்சல் அறிவிப்புகளை முடக்கும். MAILTO-ல் ஒரு சரியான மின்னஞ்சல் முகவரியை அமைப்பது, ஒரு செயல்படும் MTA இருந்தால் மட்டுமே உதவும். எனவே, அதை நம்புவதற்கு முன், சர்வரிலிருந்து மின்னஞ்சல் வெளியேறுகிறதா என்பதை உறுதிப்படுத்திக் கொள்ளுங்கள்.
பிழைத்திருத்தம் (debugging) செய்யும் போது ஒரு விதி: > /dev/null 2>&1-ஐ ஒருபோதும் சேர்க்காதீர்கள். இது ஒவ்வொரு crontab-லும் மிகவும் பொதுவாகப் பயன்படுத்தப்படும் வரியாகும், ஆனால் இது உங்களிடம் உள்ள ஒரே ஆதாரத்தை அழித்துவிடும். job சரியாக வேலை செய்த பிறகு, தேவைப்பட்டால் இதை மீண்டும் சேர்த்துக்கொள்ளலாம்.
காரணம் 5: cron சூழலில் இல்லாத சில அம்சங்களை script எதிர்பார்ப்பது
கட்டளை கண்டறியப்பட்டு அதன் வெளியீடு பெறப்பட்ட பிறகு, உங்கள் session-ல் இயல்பாகக் கிடைக்கும் பிற அம்சங்கள் cron-ல் இருக்காது.
- shell என்பது bash-ஆக இல்லாமல் இருக்கலாம்.
ls -l /bin/shமூலம் சரிபார்க்கவும். Debian மற்றும் Ubuntu-வில் இது dash-ஐக் குறிக்கும், எனவே double bracket test, arrays மற்றும்sourceஆகியவை syntax error-ஐத் தரும். script-ன் தொடக்கத்தில்#!/bin/bashவரியைச் சேர்த்து அதை இயக்கவும், அல்லது crontab-ன் மேலேSHELL-ஐ அமைக்கவும். - நீங்கள் இருந்த working directory-ல் script இயங்காது. எல்லா இடங்களிலும் absolute paths-ஐப் பயன்படுத்தவும், அல்லது script-ன் முதல் வரியில் அந்த directory-க்கு
cdசெய்யவும். "நான் நேரடியாக இயக்கும்போது வேலை செய்கிறது" என்று சொல்லப்படும் பணிகளுக்கு, relative path-ஐப் பயன்படுத்துவதே மிக முக்கியமான காரணமாகும். - உங்கள் session-ல் உள்ள locale அங்கே இருக்காது. தேதி அல்லது எண்களை வடிவமைக்கும், அல்லது உரையை வரிசைப்படுத்தும் எந்தவொரு செயலும், வெவ்வேறு
LANGசூழலில் மாறுபட்ட வெளியீட்டைத் தரலாம். அடுத்தடுத்த நிலைகளில் அந்த வெளியீடு பயன்படுத்தப்பட்டால், எதேச்சையாக நடக்கும் என்று நம்பாமல், script-லேயே locale-ஐ அமைக்கவும். - அங்கே TTY (terminal) இருக்காது. உறுதிப்படுத்தல் கேட்கும், editor-ஐத் திறக்கும் அல்லது progress bar-ஐக் காட்டும் கட்டளைகள் hang ஆகலாம் அல்லது வெளியேறலாம். அந்த tool வழங்கும் non-interactive flag-ஐச் சேர்க்கவும்.
- அங்கே SSH agent இருக்காது.
SSH_AUTH_SOCKஎன்பது cron-ன் சூழலில் இருக்காது, எனவே உங்கள் agent loaded-ஆக இருந்ததால் வேலை செய்தsshஅல்லதுrsyncகட்டளைகள் இப்போது authenticate செய்யத் தவறும். அந்தப் பணிக்குச் சொந்தமான key-ஐப் பயன்படுத்தவும். - அங்கே user session bus இருக்காது, எனவே
XDG_RUNTIME_DIRஅமைக்கப்படாத வரை cron job-லிருந்துsystemctl --userஇயங்காது. இதற்கு system unit-ஐப் பயன்படுத்துவதே சிறந்த தீர்வாகும்.
Fedora, Rocky மற்றும் Alma ஆகியவற்றில் கூடுதலாக ஒரு சந்தேகம் உள்ளது. SELinux ஆனது cron jobs-ஐக் கட்டுப்படுத்துகிறது, எனவே கோப்பு அனுமதிகள் சரியாக இருந்தாலும், எதிர்பாராத label கொண்ட பாதையை அணுகும் பணி தடுக்கப்படும். sudo ausearch -m avc -ts recent மூலம் தடைகளைச் சரிபார்க்கவும், எதையும் முடக்கும் முன் SELinux basics for a server என்பதைப் படிக்கவும்.
cron-ன் சூழலை வெளிப்படுத்தும் ஒரு நிமிட ஆய்வு
cron-ன் சூழலில் என்னென்ன மாறிகள் உள்ளன என்று ஊகிப்பதை நிறுத்திவிட்டு, அதை நேரடியாகப் படியுங்கள். அனைத்து விவரங்களையும் ஒரு கோப்பில் பதிக்கும் ஸ்கிரிப்ட் ஒன்றை எழுதி, அதை ஒவ்வொரு நிமிடமும் இயங்குமாறு அட்டவணைப்படுத்தி, சிறிது நேரம் காத்திருந்து, பின் அந்தக் கோப்பைப் படியுங்கள்.
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எந்தப் பயனரின் கணக்கில் அந்தப் பணி (job) இயங்குகிறதோ, அந்தப் பயனரின் 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 ஆகியவையே பெரும்பாலும் தோல்விக்கான காரணத்தை விளக்கிவிடும். இந்த அமைப்பில் இரண்டு விவரங்களைக் கவனிக்கவும்: சதவீதக் குறியீடுகள் (percent signs) ஸ்கிரிப்ட்டிற்குள் இருப்பதால், அங்கு cron-ன் விதிகள் பொருந்தாது; மேலும், log கோப்பு எழுதப்படும் பாதை அந்தப் பயனருக்கு எழுதும் அனுமதி (write permission) கொண்டதாக இருக்க வேண்டும்.
விடை கிடைத்தவுடன் அந்த crontab வரியை நீக்கிவிடவும். ஒவ்வொரு நிமிடமும் இயங்கி ஒரு கோப்பில் தகவலைச் சேர்க்கும் பணி, சிறிய வட்டு இடத்தைச் (disk space) சீக்கிரமே நிரப்பிவிடும், அதுவும் அமைதியாகவே நடக்கும்.
நீங்கள் குறிப்பிட்டது இந்த அட்டவணையா?
ஒரு user crontab வரியில் ஐந்து புலங்கள் (fields) உள்ளன: நிமிடம், மணிநேரம், மாதத்தின் நாள், மாதம், வாரத்தின் நாள். இவற்றில் இரண்டு புலங்கள் பயனர்களை வியக்க வைக்கும் வகையில் செயல்படுகின்றன.
மாதத்தின் நாள் மற்றும் வாரத்தின் நாள் ஆகிய இரண்டுமே * என இல்லாமல் கட்டுப்படுத்தப்பட்டிருந்தால், ஏதேனும் ஒரு புலம் பொருந்தும்போதெல்லாம் cron அந்த வேலையை இயக்கும். 0 0 13 * 5 என்பது "13-ஆம் தேதி வெள்ளிக்கிழமை" என்று பொருளல்ல. இது ஒவ்வொரு மாதமும் 13-ஆம் தேதி நள்ளிரவிலும், ஒவ்வொரு வெள்ளிக்கிழமை நள்ளிரவிலும் இயங்கும். ஒரு குறிப்பிட்ட நாளை மட்டும் தேர்வு செய்ய, இரண்டு புலங்களில் ஒன்றை * என விட்டுவிட்டு, மற்றொன்றை script-க்குள் சோதிக்க வேண்டும்.
cron கணினியின் timezone-ஐப் பயன்படுத்துகிறது. பல VPS images UTC (coordinated universal time)-ல் அமைக்கப்பட்டு வருகின்றன. எனவே, நீங்கள் 03:00 மணிக்குத் திட்டமிடும் வேலை 03:00 UTC-ல் இயங்கும், இது உங்கள் உள்ளூர் நேரத்தின் பிற்பகலாக இருக்கலாம். timedatectl உங்கள் கணினி தற்போது எந்த நேரத்தைப் பயன்படுத்துகிறது என்பதைக் காட்டும். உங்கள் மடிக்கணினியின் நேரத்தோடு இது ஒத்துப்போகும் என்று கருதாமல், உங்கள் கணினியின் நேரத்தைச் சரிபார்க்கவும்.
அட்டவணைப்படுத்துதலில் கவனிக்க வேண்டிய மேலும் இரண்டு சிக்கல்கள் உள்ளன. @reboot என்பது cron தொடங்கும்போதே இயங்கும். இது network தயாராக இருக்கும் தருணமும் அல்ல. எனவே, DNS அல்லது remote host தேவைப்படும் ஒரு வேலை, கணினி தொடங்கும் போது தோல்வியடைந்து, பின்னர் கைமுறையாக இயக்கும்போது வெற்றிபெறலாம். மேலும், ஒரு மெதுவான வேலை இயங்கிக்கொண்டிருக்கும்போதே, அதன் அடுத்த நகல் மீண்டும் தொடங்குவதைத் தடுக்க எந்தக் கட்டுப்பாடும் இல்லை. எனவே, அதை ஒரு 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-க்கு எதிராக வரிசைப்படுத்தலாம், மேலும் நூற்றுக்கணக்கான server-கள் ஒரே வினாடியில் தொடங்காமல் இருக்க randomized delay-ஐ அமைக்கலாம். உங்கள் பணிக்கு இவை தேவைப்படும்போது, VPS-ல் systemd service மற்றும் timer-ஐ அமைப்பது crontab வரியைப் பராமரிப்பதை விட எளிதானது. தோல்விக்குப் பிறகு என்ன செய்ய வேண்டும் என்பதை systemd restart policies தீர்மானிப்பதால், retry செயல்பாடுகளும் இதிலேயே அடங்கும்; 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-க்கு உள்ளேயோ உங்களுக்குத் தேவையானவற்றை அமைக்கவும். env | sort, pwd மற்றும் id ஆகியவற்றை ஒரு log file-ல் பதிவு செய்யும் ஒரு நிமிட probe job-ஐ உருவாக்கவும்; இதன் மூலம் cron-ன் உண்மையான environment-ஐ ஊகிப்பதற்குப் பதிலாக நேரடியாக வாசிக்க முடியும்.
cron எனது வேலையை உண்மையில் இயக்கியதா என்பதை எப்படிச் சரிபார்ப்பது?
daemon-ன் log-ஐ வாசிக்கவும். Debian மற்றும் Ubuntu-வில் journalctl -u cron-ஐப் பயன்படுத்தவும், அல்லது Fedora, Rocky மற்றும் Alma-வில் journalctl -u crond-ஐப் பயன்படுத்தவும்; சில images செய்திகளை rsyslog வழியாக /var/log-க்குக் கீழே உள்ள ஒரு கோப்பிற்கு அனுப்பும். உங்கள் schedule-ல் குறிப்பிட்ட நிமிடத்தில் ஒரு entry உள்ளதா என்று பார்த்து, அதில் உங்கள் கட்டளை குறிப்பிடப்பட்டுள்ளதா எனச் சரிபார்க்கவும். entry இல்லை என்றால், cron-க்கு அந்த schedule கிடைக்கவில்லை என்று அர்த்தம்; எனவே சரியான crontab-ஐத்தான் திருத்தினீர்களா என்பதை உறுதிப்படுத்தவும். முடிவு ஏதுமில்லாத entry இருந்தால், கட்டளை தொடங்கி நின்றுவிட்டது என்று அர்த்தம்; எனவே அதன் output-ஐ ஒரு redirect மூலம் capture செய்யவும்.
crontab-க்குள் ஏன் date +%Y வேலை செய்யவில்லை?
cron கட்டளைப் பகுதியில் %-ஐ ஒரு சிறப்பு குறியீடாகக் கருதுகிறது. escape செய்யப்படாத முதல் % கட்டளையை முடித்துவிடும், அதற்குப் பின் வருபவை அனைத்தும் standard input-ஆக அந்தக் கட்டளைக்கு அனுப்பப்படும், மேலும் ஒவ்வொரு கூடுதல் %-ம் ஒரு புதிய வரியாக (newline) மாறும். எனவே, date-formatted filename நீங்கள் எழுதிய நிரலுக்குச் சென்றடையாது. ஒவ்வொரு percent குறியீட்டையும் \% என escape செய்யவும், அல்லது கட்டளையை ஒரு script-க்குள் நகர்த்திவிட்டு cron-லிருந்து அந்த script-ஐ அழைக்கவும்; ஏனெனில் script-க்குள் percent குறியீட்டிற்குச் சிறப்பு அர்த்தம் இல்லை.
எனது cron job-ன் output எங்கே செல்கிறது?
இது local mail system-க்கு, crontab-ன் உரிமையாளருக்கோ அல்லது MAILTO-ல் குறிப்பிடப்பட்டுள்ளவருக்கோ அனுப்பப்படும். பெரும்பாலான VPS images-ல் mail transfer agent நிறுவப்பட்டிருக்காது, எனவே செய்தி நிராகரிக்கப்பட்டு job அமைதியாக இருப்பது போலத் தோன்றும். output-ஐ >> /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-க்கு நீங்கள் மாற்ற வேண்டியிருக்கும் சூழலில் இது சிறந்தது. output-ஐ redirect செய்யாமல் journal-ல் பெற விரும்பினால், exit status-ஐ query செய்ய முடிந்தால், network தயாரான பிறகு இயங்க வேண்டுமென்றால், தொடங்கும் நேரத்தில் சீரற்ற தாமதம் (randomized delay) தேவைப்பட்டால், அல்லது தோல்விக்குப் பிறகு மீண்டும் முயற்சிக்கும் (retry policy) வசதி தேவைப்பட்டால் timer-ஐப் பயன்படுத்தவும். இவை இரண்டையும் ஒரே server-ல் இயக்க முடியும், எனவே ஒவ்வொரு job-ன் தேவைக்கேற்ப அவற்றை ஒவ்வொன்றாக மாற்றிக்கொள்ளலாம்.