लिनक्स में क्रॉन: इतिहास, उपयोग और डिवाइस

लिनक्स में क्रॉन: इतिहास, उपयोग और डिवाइस

क्लासिक ने लिखा कि ख़ुशी के घंटे नहीं देखते। उन जंगली समय में न तो प्रोग्रामर थे और न ही यूनिक्स, लेकिन आज प्रोग्रामर निश्चित रूप से जानते हैं: क्रॉन उनके बजाय समय का ट्रैक रखेगा।

कमांड लाइन उपयोगिताएँ मेरे लिए कमजोरी और परेशानी दोनों हैं। sed, awk, WC, Cut और अन्य पुराने प्रोग्राम हर दिन हमारे सर्वर पर स्क्रिप्ट द्वारा चलाए जाते हैं। उनमें से कई क्रॉन के लिए कार्यों के रूप में डिज़ाइन किए गए हैं, जो मूल रूप से 70 के दशक का एक शेड्यूलर है।

लंबे समय तक मैंने क्रॉन का उपयोग सतही तौर पर किया, बिना विवरण में गए, लेकिन एक दिन, जब मुझे एक स्क्रिप्ट चलाते समय एक त्रुटि का सामना करना पड़ा, तो मैंने इस पर पूरी तरह से गौर करने का फैसला किया। इस तरह यह लेख सामने आया, इसे लिखते समय मैं POSIX crontab, लोकप्रिय लिनक्स वितरण में मुख्य क्रॉन विकल्प और उनमें से कुछ की संरचना से परिचित हो गया।

क्या आप लिनक्स का उपयोग कर रहे हैं और क्रॉन कार्य चला रहे हैं? क्या आप यूनिक्स में सिस्टम एप्लिकेशन आर्किटेक्चर में रुचि रखते हैं? फिर हम अपने रास्ते पर हैं!

सामग्री

प्रजाति की उत्पत्ति

उपयोगकर्ता या सिस्टम प्रोग्राम का आवधिक निष्पादन सभी ऑपरेटिंग सिस्टम में एक स्पष्ट आवश्यकता है। इसलिए, प्रोग्रामर को बहुत समय पहले ऐसी सेवाओं की आवश्यकता का एहसास हुआ जो उन्हें केंद्रीय रूप से योजना बनाने और कार्यों को निष्पादित करने की अनुमति देती है।

यूनिक्स जैसे ऑपरेटिंग सिस्टम की उत्पत्ति संस्करण 7 यूनिक्स से हुई है, जिसे पिछली शताब्दी के 70 के दशक में बेल लैब्स में विकसित किया गया था, जिसमें प्रसिद्ध केन थॉम्पसन भी शामिल थे। संस्करण 7 यूनिक्स में क्रॉन भी शामिल है, जो नियमित रूप से सुपरयूज़र कार्यों को चलाने के लिए एक सेवा है।

एक विशिष्ट आधुनिक क्रॉन एक सरल प्रोग्राम है, लेकिन मूल संस्करण का ऑपरेटिंग एल्गोरिदम और भी सरल था: सेवा एक मिनट में एक बार जागती थी, एक फ़ाइल (/etc/lib/crontab) से कार्यों के साथ एक तालिका पढ़ती थी और इसके लिए प्रदर्शन करती थी सुपरयूज़र वे कार्य जो वर्तमान समय में किए जाने चाहिए थे।

इसके बाद, सभी यूनिक्स जैसे ऑपरेटिंग सिस्टम के साथ सरल और उपयोगी सेवा के उन्नत संस्करण प्रदान किए गए।

क्रोंटैब प्रारूप के सामान्यीकृत विवरण और उपयोगिता के संचालन के बुनियादी सिद्धांतों को 1992 में यूनिक्स-जैसे ऑपरेटिंग सिस्टम के मुख्य मानक - POSIX - में शामिल किया गया था, और इस प्रकार क्रोन एक वास्तविक मानक से एक कानूनी मानक बन गया।

1987 में, पॉल विक्सी ने यूनिक्स उपयोगकर्ताओं से क्रॉन के प्रति उनकी इच्छाओं के बारे में सर्वेक्षण किया और डेमॉन का एक और संस्करण जारी किया, जिसने पारंपरिक क्रॉन की कुछ समस्याओं को ठीक किया और तालिका फ़ाइलों के सिंटैक्स का विस्तार किया।

विक्सी के तीसरे संस्करण तक क्रॉन ने POSIX आवश्यकताओं को पूरा करना शुरू कर दिया, इसके अलावा, प्रोग्राम के पास एक उदार लाइसेंस था, या यूँ कहें कि कोई लाइसेंस नहीं था, README में इच्छाओं को छोड़कर: लेखक गारंटी नहीं देता है, लेखक का नाम हटाया नहीं जा सकता, और प्रोग्राम को केवल स्रोत कोड के साथ ही बेचा जा सकता है। ये आवश्यकताएं मुफ्त सॉफ़्टवेयर के सिद्धांतों के अनुकूल साबित हुईं जो उन वर्षों में लोकप्रियता हासिल कर रही थीं, इसलिए 90 के दशक की शुरुआत में दिखाई देने वाले कुछ प्रमुख लिनक्स वितरणों ने विक्सी क्रॉन को अपने सिस्टम के रूप में लिया और आज भी इसे विकसित कर रहे हैं।

विशेष रूप से, रेड हैट और एसयूएसई ने विक्सी क्रॉन - क्रॉनी का एक कांटा विकसित किया है, और डेबियन और उबंटू कई पैच के साथ विक्सी क्रॉन के मूल संस्करण का उपयोग करते हैं।

आइए सबसे पहले POSIX में वर्णित उपयोगकर्ता उपयोगिता crontab से परिचित हों, जिसके बाद हम Vixie cron में प्रदान किए गए सिंटैक्स एक्सटेंशन और लोकप्रिय Linux वितरणों में Vixie cron की विविधताओं के उपयोग को देखेंगे। और अंत में, केक पर चेरी क्रोन डेमॉन डिवाइस का विश्लेषण है।

POSIX crontab

यदि मूल क्रॉन हमेशा सुपरयूज़र के लिए काम करता है, तो आधुनिक शेड्यूलर अक्सर सामान्य उपयोगकर्ताओं के कार्यों से निपटते हैं, जो अधिक सुरक्षित और सुविधाजनक है।

क्रोन को दो कार्यक्रमों के एक सेट के रूप में आपूर्ति की जाती है: लगातार चलने वाला क्रोन डेमॉन और उपयोगकर्ताओं के लिए उपलब्ध क्रोनटैब उपयोगिता। उत्तरार्द्ध आपको सिस्टम में प्रत्येक उपयोगकर्ता के लिए विशिष्ट कार्य तालिकाओं को संपादित करने की अनुमति देता है, जबकि डेमॉन उपयोगकर्ता और सिस्टम तालिकाओं से कार्य लॉन्च करता है।

В पॉज़िक्स मानक डेमॉन के व्यवहार का किसी भी तरह से वर्णन नहीं किया गया है और केवल उपयोगकर्ता प्रोग्राम को औपचारिक रूप दिया गया है crontab. बेशक, उपयोगकर्ता कार्यों को लॉन्च करने के लिए तंत्र का अस्तित्व निहित है, लेकिन विस्तार से वर्णित नहीं है।

क्रॉस्टैब उपयोगिता को कॉल करके, आप चार काम कर सकते हैं: संपादक में उपयोगकर्ता की कार्य तालिका को संपादित करें, तालिका को फ़ाइल से लोड करें, वर्तमान कार्य तालिका दिखाएं, और कार्य तालिका साफ़ करें। क्रॉस्टैब उपयोगिता कैसे काम करती है इसके उदाहरण:

crontab -e # редактировать таблицу задач
crontab -l # показать таблицу задач
crontab -r # удалить таблицу задач
crontab path/to/file.crontab # загрузить таблицу задач из файла

जब बुलाया गया crontab -e मानक पर्यावरण चर में निर्दिष्ट संपादक का उपयोग किया जाएगा EDITOR.

कार्य स्वयं निम्नलिखित प्रारूप में वर्णित हैं:

# строки-комментарии игнорируются
#
# задача, выполняемая ежеминутно
* * * * * /path/to/exec -a -b -c
# задача, выполняемая на 10-й минуте каждого часа
10 * * * * /path/to/exec -a -b -c
# задача, выполняемая на 10-й минуте второго часа каждого дня и использующая перенаправление стандартного потока вывода
10 2 * * * /path/to/exec -a -b -c > /tmp/cron-job-output.log

रिकॉर्ड के पहले पांच क्षेत्र: मिनट [1..60], घंटे [0..23], महीने के दिन [1..31], महीने [1..12], सप्ताह के दिन [0. .6], जहां 0 रविवार है। अंतिम, छठा, फ़ील्ड एक पंक्ति है जिसे मानक कमांड दुभाषिया द्वारा निष्पादित किया जाएगा।

पहले पाँच फ़ील्ड में, मानों को अल्पविराम से अलग करके सूचीबद्ध किया जा सकता है:

# задача, выполняемая в первую и десятую минуты каждого часа
1,10 * * * * /path/to/exec -a -b -c

या एक हाइफ़न के साथ:

# задача, выполняемая в каждую из первых десяти минут каждого часа
0-9 * * * * /path/to/exec -a -b -c

कार्य शेड्यूलिंग तक उपयोगकर्ता की पहुंच को POSIX में cron.allow और cron.deny फ़ाइलों द्वारा नियंत्रित किया जाता है, जो क्रमशः crontab तक पहुंच वाले उपयोगकर्ताओं और प्रोग्राम तक पहुंच के बिना उपयोगकर्ताओं को सूचीबद्ध करते हैं। मानक किसी भी तरह से इन फ़ाइलों के स्थान को विनियमित नहीं करता है।

मानक के अनुसार, लॉन्च किए गए कार्यक्रमों में कम से कम चार पर्यावरण चर पारित किए जाने चाहिए:

  1. होम - उपयोगकर्ता की होम निर्देशिका।
  2. लॉगनाम - उपयोगकर्ता लॉगिन।
  3. PATH वह पथ है जहाँ आप मानक सिस्टम उपयोगिताएँ पा सकते हैं।
  4. शेल - प्रयुक्त कमांड दुभाषिया का पथ।

विशेष रूप से, POSIX इस बारे में कुछ नहीं कहता है कि इन चरों के लिए मान कहाँ से आते हैं।

सर्वश्रेष्ठ विक्रेता - विक्सी क्रॉन 3.0pl1

लोकप्रिय क्रॉन वेरिएंट का सामान्य पूर्वज विक्सी क्रॉन 3.0pl1 है, जिसे 1992 में comp.sources.unix मेलिंग सूची में पेश किया गया था। हम इस संस्करण की मुख्य विशेषताओं पर अधिक विस्तार से विचार करेंगे।

विक्सी क्रॉन दो कार्यक्रमों (क्रॉन और क्रोंटैब) में आता है। हमेशा की तरह, डेमॉन सिस्टम कार्य तालिका और व्यक्तिगत उपयोगकर्ता कार्य तालिकाओं से कार्यों को पढ़ने और चलाने के लिए जिम्मेदार है, और क्रॉस्टैब उपयोगिता उपयोगकर्ता तालिकाओं को संपादित करने के लिए जिम्मेदार है।

कार्य तालिका और कॉन्फ़िगरेशन फ़ाइलें

सुपरयूजर कार्य तालिका /etc/crontab में स्थित है। सिस्टम तालिका का सिंटैक्स विक्सी क्रॉन के सिंटैक्स से मेल खाता है, इस अपवाद के साथ कि इसमें छठा कॉलम उस उपयोगकर्ता का नाम इंगित करता है जिसके तहत कार्य लॉन्च किया गया है:

# Запускается ежеминутно от пользователя vlad
* * * * * vlad /path/to/exec

नियमित उपयोगकर्ता कार्य तालिकाएँ /var/cron/tabs/username में स्थित होती हैं और समान सिंटैक्स का उपयोग करती हैं। जब आप एक उपयोगकर्ता के रूप में क्रोंटैब उपयोगिता चलाते हैं, तो ये फ़ाइलें संपादित होती हैं।

क्रॉस्टैब तक पहुंच वाले उपयोगकर्ताओं की सूची /var/cron/allow और /var/cron/deny फ़ाइलों में प्रबंधित की जाती है, जहां आपको बस एक अलग पंक्ति में उपयोगकर्ता नाम दर्ज करना होगा।

विस्तारित वाक्यविन्यास

POSIX crontab की तुलना में, पॉल विक्सी के समाधान में उपयोगिता के कार्य तालिकाओं के सिंटैक्स में कई बहुत उपयोगी संशोधन शामिल हैं।

एक नया तालिका सिंटैक्स उपलब्ध हो गया है: उदाहरण के लिए, आप सप्ताह या महीनों के दिनों को नाम से निर्दिष्ट कर सकते हैं (सोम, मंगल, और इसी तरह):

# Запускается ежеминутно по понедельникам и вторникам в январе
* * * Jan Mon,Tue /path/to/exec

आप वह चरण निर्दिष्ट कर सकते हैं जिसके माध्यम से कार्य लॉन्च किए जाते हैं:

# Запускается с шагом в две минуты
*/2 * * * Mon,Tue /path/to/exec

चरणों और अंतरालों को मिलाया जा सकता है:

# Запускается с шагом в две минуты в первых десять минут каждого часа
0-10/2 * * * * /path/to/exec

सामान्य सिंटैक्स के सहज विकल्प समर्थित हैं (रिबूट, वार्षिक, वार्षिक, मासिक, साप्ताहिक, दैनिक, मध्यरात्रि, प्रति घंटा):

# Запускается после перезагрузки системы
@reboot /exec/on/reboot
# Запускается раз в день
@daily /exec/daily
# Запускается раз в час
@hourly /exec/daily

कार्य निष्पादन वातावरण

विक्सी क्रॉन आपको चल रहे एप्लिकेशन के वातावरण को बदलने की अनुमति देता है।

पर्यावरण चर USER, LOGNAME और HOME केवल डेमॉन द्वारा प्रदान नहीं किए जाते हैं, बल्कि एक फ़ाइल से लिए जाते हैं पासवर्ड. PATH वेरिएबल को "/usr/bin:/bin" पर सेट किया गया है और SHELL वेरिएबल को "/bin/sh" पर सेट किया गया है। उपयोगकर्ता तालिकाओं में LOGNAME को छोड़कर सभी वेरिएबल्स के मान बदले जा सकते हैं।

कुछ पर्यावरण चर (विशेष रूप से शेल और होम) का उपयोग क्रॉन द्वारा कार्य को चलाने के लिए किया जाता है। यहां बताया गया है कि कस्टम कार्यों को चलाने के लिए मानक sh के बजाय बैश का उपयोग कैसा दिख सकता है:

SHELL=/bin/bash
HOME=/tmp/
# exec будет запущен bash-ем в /tmp/
* * * * * /path/to/exec

अंततः, तालिका में परिभाषित सभी पर्यावरण चर (क्रॉन द्वारा प्रयुक्त या प्रक्रिया द्वारा आवश्यक) को चल रहे कार्य में पास कर दिया जाएगा।

फ़ाइलों को संपादित करने के लिए, crontab VISUAL या EDITOR पर्यावरण चर में निर्दिष्ट संपादक का उपयोग करता है। यदि जिस वातावरण में क्रोंटैब चलाया गया था, उसमें ये चर परिभाषित नहीं हैं, तो "/usr/ucb/vi" का उपयोग किया जाता है (यूसीबी संभवतः कैलिफोर्निया विश्वविद्यालय, बर्कले है)।

डेबियन और उबंटू पर क्रॉन

डेबियन और डेरिवेटिव वितरण के डेवलपर्स ने जारी किया है अत्यधिक संशोधित संस्करण विक्सी क्रॉन संस्करण 3.0pl1. तालिका फ़ाइलों के सिंटैक्स में कोई अंतर नहीं है; उपयोगकर्ताओं के लिए यह वही विक्सी क्रोन है। सबसे बड़ी नई सुविधा: समर्थन syslog, SELinux и PAM.

कम ध्यान देने योग्य, लेकिन ठोस परिवर्तनों में कॉन्फ़िगरेशन फ़ाइलों और कार्य तालिकाओं का स्थान शामिल है।

डेबियन में उपयोगकर्ता तालिकाएँ /var/spool/cron/crontabs निर्देशिका में स्थित हैं, सिस्टम तालिका अभी भी वहाँ है - /etc/crontab में। डेबियन पैकेज-विशिष्ट कार्य तालिकाएँ /etc/cron.d में रखी जाती हैं, जहाँ से क्रॉन डेमॉन स्वचालित रूप से उन्हें पढ़ता है। उपयोगकर्ता अभिगम नियंत्रण /etc/cron.allow और /etc/cron.deny फ़ाइलों द्वारा नियंत्रित किया जाता है।

डिफ़ॉल्ट शेल अभी भी /bin/sh है, जो डेबियन में एक छोटा POSIX-संगत शेल है पानी का छींटा, बिना किसी कॉन्फ़िगरेशन को पढ़े (गैर-इंटरैक्टिव मोड में) लॉन्च किया गया।

डेबियन के नवीनतम संस्करणों में क्रॉन को सिस्टमडी के माध्यम से लॉन्च किया गया है, और लॉन्च कॉन्फ़िगरेशन को /lib/systemd/system/cron.service में देखा जा सकता है। सेवा कॉन्फ़िगरेशन में कुछ खास नहीं है; किसी भी अधिक सूक्ष्म कार्य प्रबंधन को प्रत्येक उपयोगकर्ता के क्रॉस्टैब में सीधे घोषित पर्यावरण चर के माध्यम से किया जा सकता है।

RedHat, Fedora और CentOS पर क्रोनी

cronie - विक्सी क्रॉन संस्करण 4.1 का कांटा। डेबियन की तरह, सिंटैक्स नहीं बदला है, लेकिन PAM और SELinux के लिए समर्थन, क्लस्टर में काम करना, इनोटिफाई का उपयोग करके फ़ाइलों को ट्रैक करना और अन्य सुविधाओं को जोड़ा गया है।

डिफ़ॉल्ट कॉन्फ़िगरेशन सामान्य स्थानों पर है: सिस्टम तालिका /etc/crontab में है, पैकेज अपनी तालिकाएँ /etc/cron.d में रखते हैं, उपयोगकर्ता तालिकाएँ /var/spool/cron/crontab में जाती हैं।

डेमॉन सिस्टमड नियंत्रण के तहत चलता है, सेवा कॉन्फ़िगरेशन /lib/systemd/system/crond.service है।

Red Hat-जैसे वितरण पर, /bin/sh का उपयोग स्टार्टअप पर डिफ़ॉल्ट रूप से किया जाता है, जो मानक बैश है। यह ध्यान दिया जाना चाहिए कि /bin/sh के माध्यम से क्रॉन जॉब चलाते समय, बैश शेल POSIX-संगत मोड में शुरू होता है और गैर-इंटरैक्टिव मोड में चलने पर कोई अतिरिक्त कॉन्फ़िगरेशन नहीं पढ़ता है।

SLES और openSUSE में क्रोनी

जर्मन वितरण एसएलईएस और इसके व्युत्पन्न ओपनएसयूएसई एक ही क्रोनी का उपयोग करते हैं। यहां डेमॉन को सिस्टमडी के तहत भी लॉन्च किया गया है, सेवा कॉन्फ़िगरेशन /usr/lib/systemd/system/cron.service में स्थित है। कॉन्फ़िगरेशन: /etc/crontab, /etc/cron.d, /var/spool/cron/tabs. /bin/sh वही बैश है जो POSIX-संगत गैर-इंटरैक्टिव मोड में चल रहा है।

विक्सी क्रॉन डिवाइस

विक्सी क्रॉन की तुलना में क्रॉन के आधुनिक वंशज मौलिक रूप से नहीं बदले हैं, लेकिन फिर भी उन्होंने नई सुविधाएँ हासिल कर ली हैं जिनकी कार्यक्रम के सिद्धांतों को समझने के लिए आवश्यकता नहीं है। इनमें से कई एक्सटेंशन खराब तरीके से डिज़ाइन किए गए हैं और कोड को भ्रमित करते हैं। पॉल विक्सी द्वारा लिखित मूल क्रॉन स्रोत कोड को पढ़ना सुखद है।

इसलिए, मैंने विकास की दोनों शाखाओं के लिए सामान्य क्रॉन प्रोग्राम के उदाहरण का उपयोग करके क्रॉन डिवाइस का विश्लेषण करने का निर्णय लिया - विक्सी क्रॉन 3.0pl1। मैं पढ़ने में कठिनाई पैदा करने वाले ifdefs को हटाकर और छोटी-मोटी जानकारियाँ छोड़ कर उदाहरणों को सरल बना दूँगा।

दानव के कार्य को कई चरणों में विभाजित किया जा सकता है:

  1. कार्यक्रम का आरंभ.
  2. चलाने के लिए कार्यों की सूची एकत्रित करना और अद्यतन करना।
  3. मुख्य क्रॉन लूप चल रहा है।
  4. कोई कार्य प्रारंभ करें.

आइए उन्हें क्रम से देखें।

प्रारंभ

प्रारंभ होने पर, प्रक्रिया तर्कों की जाँच करने के बाद, क्रॉन SIGCHLD और SIGHUP सिग्नल हैंडलर स्थापित करता है। पहला व्यक्ति चाइल्ड प्रक्रिया की समाप्ति के बारे में लॉग प्रविष्टि बनाता है, दूसरा लॉग फ़ाइल के फ़ाइल डिस्क्रिप्टर को बंद करता है:

signal(SIGCHLD, sigchld_handler);
signal(SIGHUP, sighup_handler);

क्रॉन डेमॉन हमेशा सिस्टम पर अकेले चलता है, केवल एक सुपरयूजर के रूप में और मुख्य क्रॉन निर्देशिका से। निम्नलिखित कॉल डेमॉन प्रक्रिया के पीआईडी ​​के साथ एक लॉक फ़ाइल बनाते हैं, सुनिश्चित करें कि उपयोगकर्ता सही है और वर्तमान निर्देशिका को मुख्य में बदलें:

acquire_daemonlock(0);
set_cron_uid();
set_cron_cwd();

डिफ़ॉल्ट पथ सेट है, जिसका उपयोग प्रक्रियाएं शुरू करते समय किया जाएगा:

setenv("PATH", _PATH_DEFPATH, 1);

फिर प्रक्रिया को "डेमोनाइज़्ड" किया जाता है: यह फोर्क को कॉल करके और चाइल्ड प्रक्रिया में एक नया सत्र (सेटसिड को कॉल करके) प्रक्रिया की एक चाइल्ड कॉपी बनाता है। मूल प्रक्रिया की अब आवश्यकता नहीं है, और यह बाहर निकल जाती है:

switch (fork()) {
case -1:
    /* критическая ошибка и завершение работы */
    exit(0);
break;
case 0:
    /* дочерний процесс */
    (void) setsid();
break;
default:
    /* родительский процесс завершает работу */
    _exit(0);
}

मूल प्रक्रिया की समाप्ति से लॉक फ़ाइल पर लगा लॉक खुल जाता है। इसके अलावा, बच्चे को फ़ाइल में पीआईडी ​​​​अद्यतन करना आवश्यक है। इसके बाद, कार्य डेटाबेस भरा जाता है:

/* повторный захват лока */
acquire_daemonlock(0);

/* Заполнение БД  */
database.head = NULL;
database.tail = NULL;
database.mtime = (time_t) 0;
load_database(&database);

फिर क्रॉन मुख्य कार्य चक्र पर आगे बढ़ता है। लेकिन उससे पहले, कार्य सूची को लोड करने पर एक नज़र डालना उचित है।

कार्य सूची एकत्रित करना एवं अद्यतन करना

लोड_डेटाबेस फ़ंक्शन कार्यों की सूची लोड करने के लिए जिम्मेदार है। यह मुख्य सिस्टम क्रॉस्टैब और उपयोगकर्ता फ़ाइलों वाली निर्देशिका की जाँच करता है। यदि फ़ाइलें और निर्देशिका नहीं बदली हैं, तो कार्य सूची दोबारा नहीं पढ़ी जाती है। अन्यथा, कार्यों की एक नई सूची बननी शुरू हो जाती है।

विशेष फ़ाइल और तालिका नामों के साथ एक सिस्टम फ़ाइल लोड करना:

/* если файл системной таблицы изменился, перечитываем */
if (syscron_stat.st_mtime) {
    process_crontab("root", "*system*",
    SYSCRONTAB, &syscron_stat,
    &new_db, old_db);
}

उपयोगकर्ता तालिकाओं को लूप में लोड करना:

while (NULL != (dp = readdir(dir))) {
    char    fname[MAXNAMLEN+1],
            tabname[MAXNAMLEN+1];
    /* читать файлы с точкой не надо*/
    if (dp->d_name[0] == '.')
            continue;
    (void) strcpy(fname, dp->d_name);
    sprintf(tabname, CRON_TAB(fname));
    process_crontab(fname, fname, tabname,
                    &statbuf, &new_db, old_db);
}

जिसके बाद पुराने डेटाबेस को नए डेटाबेस से बदल दिया जाता है।

उपरोक्त उदाहरणों में, प्रोसेस_क्रॉंटैब फ़ंक्शन कॉल सत्यापित करता है कि तालिका फ़ाइल नाम से मेल खाने वाला उपयोगकर्ता मौजूद है (जब तक कि वह सुपरयूज़र न हो) और फिर लोड_यूज़र को कॉल करता है। उत्तरार्द्ध पहले से ही फ़ाइल को पंक्ति दर पंक्ति पढ़ता है:

while ((status = load_env(envstr, file)) >= OK) {
    switch (status) {
    case ERR:
        free_user(u);
        u = NULL;
        goto done;
    case FALSE:
        e = load_entry(file, NULL, pw, envp);
        if (e) {
            e->next = u->crontab;
            u->crontab = e;
        }
        break;
    case TRUE:
        envp = env_set(envp, envstr);
        break;
    }
}

यहां, या तो पर्यावरण चर को लोड_एनवी / एनवी_सेट फ़ंक्शन का उपयोग करके सेट किया जाता है (फॉर्म वीएआर = मान की पंक्तियां), या लोड_एंट्री फ़ंक्शन का उपयोग करके कार्य विवरण पढ़ा जाता है (* * * * * / पथ / से / निष्पादन)।

लोड_एंट्री लौटाने वाली प्रविष्टि इकाई हमारा कार्य है, जिसे कार्यों की सामान्य सूची में रखा गया है। फ़ंक्शन स्वयं समय प्रारूप का वर्बोज़ विश्लेषण करता है, लेकिन हम पर्यावरण चर और कार्य लॉन्च पैरामीटर के निर्माण में अधिक रुचि रखते हैं:

/* пользователь и группа для запуска задачи берутся из passwd*/
e->uid = pw->pw_uid;
e->gid = pw->pw_gid;

/* шелл по умолчанию (/bin/sh), если пользователь не указал другое */
e->envp = env_copy(envp);
if (!env_get("SHELL", e->envp)) {
    sprintf(envstr, "SHELL=%s", _PATH_BSHELL);
    e->envp = env_set(e->envp, envstr);
}
/* домашняя директория */
if (!env_get("HOME", e->envp)) {
    sprintf(envstr, "HOME=%s", pw->pw_dir);
    e->envp = env_set(e->envp, envstr);
}
/* путь для поиска программ */
if (!env_get("PATH", e->envp)) {
    sprintf(envstr, "PATH=%s", _PATH_DEFPATH);
    e->envp = env_set(e->envp, envstr);
}
/* имя пользовтеля всегда из passwd */
sprintf(envstr, "%s=%s", "LOGNAME", pw->pw_name);
e->envp = env_set(e->envp, envstr);

मुख्य लूप कार्यों की वर्तमान सूची के साथ काम करता है।

मुख्य घेरा

संस्करण 7 यूनिक्स के मूल क्रॉन ने काफी सरलता से काम किया: इसने कॉन्फ़िगरेशन को एक लूप में फिर से पढ़ा, वर्तमान मिनट के कार्यों को सुपरयूजर के रूप में लॉन्च किया, और अगले मिनट की शुरुआत तक सो गया। पुरानी मशीनों पर इस सरल दृष्टिकोण के लिए बहुत अधिक संसाधनों की आवश्यकता होती है।

SysV में एक वैकल्पिक संस्करण प्रस्तावित किया गया था, जिसमें डेमॉन या तो निकटतम मिनट तक जिसके लिए कार्य परिभाषित किया गया था, या 30 मिनट के लिए सो गया था। इस मोड में कॉन्फ़िगरेशन को दोबारा पढ़ने और कार्यों की जांच करने के लिए कम संसाधनों की खपत हुई, लेकिन कार्यों की सूची को जल्दी से अपडेट करना असुविधाजनक हो गया।

विक्सी क्रॉन एक मिनट में एक बार कार्य सूचियों की जाँच करने के लिए लौट आया, सौभाग्य से 80 के दशक के अंत तक मानक यूनिक्स मशीनों पर काफी अधिक संसाधन थे:

/* первичная загрузка задач */
load_database(&database);
/* запустить задачи, поставленные к выполнению после перезагрузки системы */
run_reboot_jobs(&database);
/* сделать TargetTime началом ближайшей минуты */
cron_sync();
while (TRUE) {
    /* выполнить задачи, после чего спать до TargetTime с поправкой на время, потраченное на задачи */
    cron_sleep();

    /* перечитать конфигурацию */
    load_database(&database);

    /* собрать задачи для данной минуты */
    cron_tick(&database);

    /* перевести TargetTime на начало следующей минуты */
    TargetTime += 60;
}

Cron_sleep फ़ंक्शन सीधे कार्यों को निष्पादित करने में शामिल होता है, जो job_runqueue (कार्यों की गणना करें और चलाएं) और do_command (प्रत्येक व्यक्तिगत कार्य को चलाएं) फ़ंक्शन को कॉल करता है। अंतिम फ़ंक्शन अधिक विस्तार से जांचने लायक है।

कोई कार्य चलाना

Do_command फ़ंक्शन को अच्छी यूनिक्स शैली में निष्पादित किया जाता है, अर्थात, यह कार्य को अतुल्यकालिक रूप से करने के लिए एक कांटा करता है। मूल प्रक्रिया कार्यों को लॉन्च करना जारी रखती है, चाइल्ड प्रक्रिया कार्य प्रक्रिया तैयार करती है:

switch (fork()) {
case -1:
    /*не смогли выполнить fork */
    break;
case 0:
    /* дочерний процесс: на всякий случай еще раз пробуем захватить главный лок */
    acquire_daemonlock(1);
    /* переходим к формированию процесса задачи */
    child_process(e, u);
    /* по завершению дочерний процесс заканчивает работу */
    _exit(OK_EXIT);
    break;
default:
    /* родительский процесс продолжает работу */
    break;
}

चाइल्ड_प्रोसेस में बहुत सारे तर्क हैं: यह मानक आउटपुट और त्रुटि स्ट्रीम को अपने आप में लेता है, फिर इसे मेल पर भेजने के लिए (यदि MAILTO पर्यावरण चर कार्य तालिका में निर्दिष्ट है), और अंत में, मुख्य की प्रतीक्षा करता है कार्य को पूरा करने की प्रक्रिया.

कार्य प्रक्रिया दूसरे कांटे से बनती है:

switch (vfork()) {
case -1:
    /* при ошибки сразу завершается работа */
    exit(ERROR_EXIT);
case 0:
    /* процесс-внук формирует новую сессию, терминал и т.д.
     */
    (void) setsid();

    /*
     * дальше многословная настройка вывода процесса, опустим для краткости
     */

    /* смена директории, пользователя и группы пользователя,
     * то есть процесс больше не суперпользовательский
     */
    setgid(e->gid);
    setuid(e->uid);
    chdir(env_get("HOME", e->envp));

    /* запуск самой команды
     */
    {
        /* переменная окружения SHELL указывает на интерпретатор для запуска */
        char    *shell = env_get("SHELL", e->envp);

        /* процесс запускается без передачи окружения родительского процесса,
         * то есть именно так, как описано в таблице задач пользователя  */
        execle(shell, shell, "-c", e->cmd, (char *)0, e->envp);

        /* ошибка — и процесс на запустился? завершение работы */
        perror("execl");
        _exit(ERROR_EXIT);
    }
    break;
default:
    /* сам процесс продолжает работу: ждет завершения работы и вывода */
    break;
}

क्रॉन मूलतः बस इतना ही है। मैंने कुछ दिलचस्प विवरण छोड़ दिए, उदाहरण के लिए, दूरस्थ उपयोगकर्ताओं के लिए लेखांकन, लेकिन मैंने मुख्य बात रेखांकित की।

अंतभाषण

क्रॉन आश्चर्यजनक रूप से सरल और उपयोगी प्रोग्राम है, जो यूनिक्स दुनिया की सर्वोत्तम परंपराओं में बनाया गया है। वह कुछ अतिरिक्त नहीं करती, लेकिन वह कई दशकों से अपना काम शानदार ढंग से कर रही है। उबंटू के साथ आने वाले संस्करण के लिए कोड प्राप्त करने में एक घंटे से अधिक समय नहीं लगा, और मुझे बहुत मज़ा आया! मुझे आशा है कि मैं इसे आपके साथ साझा करने में सक्षम था।

मैं आपके बारे में नहीं जानता, लेकिन मुझे यह जानकर थोड़ा दुख हुआ कि आधुनिक प्रोग्रामिंग, अत्यधिक जटिल और अत्यधिक अमूर्त होने की प्रवृत्ति के साथ, लंबे समय से ऐसी सरलता के लिए अनुकूल नहीं रही है।

क्रॉन के कई आधुनिक विकल्प हैं: सिस्टमडी-टाइमर आपको निर्भरता के साथ जटिल सिस्टम को व्यवस्थित करने की अनुमति देते हैं, एफक्रॉन आपको कार्यों द्वारा संसाधन खपत को अधिक लचीले ढंग से विनियमित करने की अनुमति देता है। लेकिन व्यक्तिगत रूप से, सबसे सरल क्रोंटैब मेरे लिए हमेशा पर्याप्त था।

संक्षेप में, यूनिक्स से प्यार करें, सरल प्रोग्राम का उपयोग करें और अपने प्लेटफ़ॉर्म के लिए मन पढ़ना न भूलें!

स्रोत: www.habr.com

एक टिप्पणी जोड़ें