पर्यावरण चर बनाम स्थितिगत पैरामीटर
इससे पहले कि हम $INTEGER
चर के प्रकार पर चर्चा करना शुरू करें , हमें यह समझने की आवश्यकता है कि वे वास्तव में क्या हैं और वे पर्यावरण चर से कैसे भिन्न होते हैं। चर जैसे $INTEGER
स्थितिगत मापदंडों को कहा जाता है। यह POSIX (पोर्टेबल ऑपरेटिंग सिस्टम इंटरफ़ेस) मानक, खंड 2.1 (जोर मेरा) में वर्णित है :
- शेल एक फ़ंक्शन निष्पादित करता है (फ़ंक्शन परिभाषा कमांड देखें), बिल्ट-इन (विशेष निर्मित-उपयोगिताओं को देखें), निष्पादन योग्य फ़ाइल या स्क्रिप्ट, स्थिति के मापदंडों के रूप में तर्कों के नाम 1 से n तक गिने, और कमांड का नाम। (या स्क्रिप्ट के भीतर एक फ़ंक्शन के मामले में, स्थिति के पैरामीटर के रूप में स्क्रिप्ट का नाम) 0 गिना गया (कमांड खोज और निष्पादन देखें)।
इसके विपरीत, चर जैसे कि $HOME
और $PATH
पर्यावरण चर हैं। उनकी परिभाषा मानक की धारा 8 में वर्णित है :
इस अध्याय में परिभाषित पर्यावरण चर कई उपयोगिताओं, कार्यों और अनुप्रयोगों के संचालन को प्रभावित करते हैं। अन्य पर्यावरण चर हैं जो केवल विशिष्ट उपयोगिताओं के लिए रुचि रखते हैं। पर्यावरण चर जो केवल एक उपयोगिता पर लागू होते हैं, उन्हें उपयोगिता विवरण के भाग के रूप में परिभाषित किया जाता है।
उनके विवरण पर ध्यान दें। स्थितिगत पैरामीटर एक कमांड के सामने प्रकट होने के लिए होते हैं, अर्थात command positional_arg_1 positional_arg_2...
। वे उपयोगकर्ता द्वारा यह बताने के लिए प्रदान किए जाते हैं कि विशेष रूप से क्या करना है। जब आप ऐसा करते हैं echo 'Hello' 'World'
, तो यह Hello
और World
स्ट्रिंग्स को प्रिंट करेगा , क्योंकि ये स्थिति के पैरामीटर हैं echo
- जिन चीजों को आप echo
संचालित करना चाहते हैं। और echo
इस तरह बनाया गया है कि यह स्थितिजन्य मापदंडों को स्ट्रिंग्स के रूप में मुद्रित करने के लिए समझता है (जब तक कि वे वैकल्पिक झंडे में से एक न हों -n
)। यदि आप अलग-अलग कमांड के साथ ऐसा करते हैं तो यह समझ में नहीं आता कि क्या Hello
और क्याWorld
क्योंकि शायद यह एक संख्या की उम्मीद है। ध्यान दें कि स्थितिगत पैरामीटर "विरासत में नहीं" हैं - एक बच्चे की प्रक्रिया को माता-पिता की स्थितिगत मापदंडों के बारे में नहीं पता है जब तक कि स्पष्ट रूप से बच्चे की प्रक्रिया के लिए पारित नहीं किया जाता है। अक्सर आप स्थितीय मापदंडों को रैपर स्क्रिप्ट्स के साथ पास करते हुए देखते हैं - जो कि पहले से ही कमांड के मौजूदा उदाहरण के लिए जाँच करते हैं या वास्तविक कमांड के लिए अतिरिक्त स्थितीय मापदंडों को जोड़ते हैं जिन्हें कहा जाएगा।
इसके विपरीत, पर्यावरण चर कई कार्यक्रमों को प्रभावित करने के लिए होते हैं। वे पर्यावरण चर रहे हैं , क्योंकि वे कार्यक्रम के बाहर ही सेट कर रहे हैं (नीचे इस पर और अधिक)। इस तरह के रूप में कुछ वातावरण चर HOME
या PATH
विशिष्ट स्वरूप, विशेष अर्थ है, और वे प्रत्येक कार्यक्रम के लिए एक ही मतलब होगा। HOME
वैरिएबल का अर्थ बाहरी उपयोगिता जैसे /usr/bin/find
या आपके शेल (और इसके परिणामस्वरूप स्क्रिप्ट) से होता है - यह उपयोगकर्ता नाम का होम डायरेक्टरी है जिसके तहत प्रक्रिया चलती है। उदाहरण के लिए, विशिष्ट चर व्यवहार के लिए पर्यावरण चर का उपयोग किया जा सकता हैUID
पर्यावरण चर का उपयोग यह जांचने के लिए किया जा सकता है कि स्क्रिप्ट रूट विशेषाधिकारों के साथ चलती है या नहीं और तदनुसार विशिष्ट कार्यों के लिए शाखा। पर्यावरण चर अंतर्निहित हैं - बच्चे की प्रक्रियाओं को माता-पिता के पर्यावरण की नकल मिलती है। यह भी देखें कि यदि प्रक्रियाएं माता-पिता के वातावरण को विरासत में देती हैं, तो हमें निर्यात की आवश्यकता क्यों है?
संक्षेप में, मुख्य अंतर यह है कि पर्यावरण चर को कमांड के बाहर सेट किया जाता है और इसका मतलब विविध (आमतौर पर) नहीं होता है, जबकि स्थितिगत पैरामीटर ऐसी चीजें हैं जो कमांड द्वारा संसाधित होने वाली होती हैं और वे बदल जाती हैं।
सिर्फ शेल कॉन्सेप्ट नहीं
मैंने टिप्पणियों से देखा है कि आप टर्मिनल और शेल को मिला रहे हैं, और वास्तव में आपको वास्तविक टर्मिनलों के बारे में पढ़ने की सलाह देंगे जो एक बार भौतिक उपकरण थे। आजकल, "टर्मिनल" जिसका हम आम तौर पर उल्लेख कर रहे हैं, काली पृष्ठभूमि और हरे रंग की पाठ वाली खिड़की वास्तव में सॉफ्टवेयर है, एक प्रक्रिया है। टर्मिनल एक प्रोग्राम है जो एक शेल चलाता है, जबकि शेल भी एक प्रोग्राम है, लेकिन एक वह है जो पढ़ता है कि आप क्या निष्पादित करने के लिए टाइप करते हैं (यानी, यदि यह इंटरैक्टिव शेल है, तो गैर-इंटरैक्टिव शेल स्क्रिप्ट और sh -c 'echo foo'
इनवोकेशन के प्रकार हैं)। यहाँ गोले पर अधिक ।
यह एक महत्वपूर्ण अंतर है, लेकिन यह पहचानना भी महत्वपूर्ण है कि टर्मिनल एक कार्यक्रम है और इसलिए पर्यावरण और पोजिशनिंग मापदंडों के समान नियमों का पालन करता है। gnome-terminal
जब आपका प्रारंभ आपके SHELL
पर्यावरण चर को देखेगा , और आपके लिए उपयुक्त डिफ़ॉल्ट शेल को स्पॉन करेगा, जब तक आप कुछ अन्य कमांड को निर्दिष्ट नहीं करते -e
। मान लीजिए कि मैंने अपने डिफ़ॉल्ट शेल को बदल दिया है ksh
- सूक्ति-टर्मिनल ksh
इसके बजाय स्पॉन करेगा bash
। यह भी एक उदाहरण है कि कार्यक्रमों द्वारा पर्यावरण का उपयोग कैसे किया जाता है। अगर मैं स्पष्ट रूप से बता gnome-terminal
के साथ -e
विशिष्ट खोल चलाने के लिए - यह यह करना होगा, लेकिन यह स्थायी नहीं किया जाएगा। इसके विपरीत, पर्यावरण का मतलब ज्यादातर अनछुए (बाद में अधिक) होता है।
तो जैसा कि आप देख सकते हैं, पर्यावरण और स्थितीय चर दोनों एक प्रक्रिया / आदेश के गुण हैं, न कि केवल शेल। जब शेल स्क्रिप्ट की बात आती है, तो वे उस मॉडल का भी पालन करते हैं जो सी प्रोग्रामिंग भाषा द्वारा निर्धारित किया गया था। उदाहरण के लिए C main
फ़ंक्शन को लें, जो आमतौर पर दिखता है
int main(int argc, char **argv)
, जहां argc
कमांड-लाइन तर्कों की संख्या है और argv
प्रभावी रूप से कमांड-लाइन मापदंडों की सरणी है, और फिर उपयोगकर्ता के घर निर्देशिका पथ, निर्देशिकाओं की सूची, जहां हम निष्पादन योग्य की तलाश कर सकते हैं, आदि जैसी चीजों तक पहुंचने के लिए environ
फ़ंक्शन (लिनक्स पर man -e 7 environ
) है PATH
। शैल लिपियों को भी इसी तरह से तैयार किया गया है। शेल शब्दावली में, हमारे पास स्थितीय पैरामीटर हैं $1
, $2
और आगे, जबकि $#
स्थितीय मापदंडों की संख्या है। किस बारे में $0
? यह स्वयं निष्पादन योग्य का नाम है, जिसे फिर से सी प्रोग्रामिंग भाषा से भी तैयार किया गया है - argv[0]
यह आपके सी "निष्पादन योग्य" का नाम होगा। और यह अधिकांश प्रोग्रामिंग और स्क्रिप्टिंग भाषाओं के लिए काफी हद तक सही है ।
इंटरएक्टिव बनाम गैर-इंटरैक्टिव गोले
एक चीज़ जो मैंने पहले ही बताई है, वह है इंटरएक्टिव और नॉन-इंटरेक्टिव गोले का अंतर । प्रॉम्प्ट जहाँ आप कमांड्स में टाइप करते हैं - यह इंटरैक्टिव है, यह उपयोगकर्ता के साथ इंटरैक्ट करता है। इसके विपरीत जब आपके पास एक शेल स्क्रिप्ट होती है या आप bash -c''
गैर-संवादात्मक होते हैं।
और यहीं से भेद महत्वपूर्ण हो जाता है। वह शेल जो आप पहले से चला रहे हैं, एक प्रक्रिया है, जिसे स्थितीय मापदंडों के साथ देखा गया था ( bash
लॉगिन शेल के लिए एक है "... जिसका तर्क शून्य का पहला वर्ण a है - या किसी ने - thelogin विकल्प से शुरू किया है।" ( संदर्भ ) )
इसके विपरीत, स्क्रिप्ट और -c
विकल्प के साथ लॉन्च किए गए गोले $1
और $2
तर्कों का लाभ उठा सकते हैं । उदाहरण के लिए,
$ bash -c 'echo $1; stat $2' sh 'Hello World' /etc/passwd
Hello World
File: '/etc/passwd'
Size: 2913 Blocks: 8 IO Block: 4096 regular file
Device: 801h/2049d Inode: 6035604 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2017-08-12 14:48:37.125879962 -0600
Modify: 2017-08-12 14:48:37.125879962 -0600
Change: 2017-08-12 14:48:37.137879811 -0600
Birth: -
ध्यान दें कि मैंने sh
वहां भी उपयोग किया है, क्योंकि -c
विकल्प का छोटा क्वर्की पहले स्थितीय पैरामीटर को लेना है और इसे असाइन करना है $0
, आमतौर पर प्रोग्राम का नाम होने के विपरीत।
एक और बात जो नोटिस करना महत्वपूर्ण है, वह यह है कि स्थितिगत मापदंड वही हैं जिन्हें मैं "फ्रैमेबल" कहता हूं। ध्यान दें कि कैसे, हमने पहली बार bash
अपने स्वयं के स्थितीय मापदंडों के साथ लॉन्च किया था , लेकिन वे स्थितियां मापदंडों के लिए echo
और बन गईं stat
। और प्रत्येक कार्यक्रम इसे अपने तरीके से समझता है। यदि हमने stat
एक स्ट्रिंग दी Hello World
और कोई फाइल नहीं है तो Hello World
यह एक त्रुटि उत्पन्न करेगा; bash
इसे सिर्फ एक साधारण स्ट्रिंग के रूप में मानते हैं, लेकिन stat
उस स्ट्रिंग को एक मौजूदा फ़ाइल नाम होने की उम्मीद करते हैं। इसके विपरीत, सभी कार्यक्रम सहमत होंगे कि पर्यावरण चर HOME
एक निर्देशिका है (जब तक कि प्रोग्रामर ने इसे अनुचित तरीके से कोडित नहीं किया है)।
क्या हम पर्यावरण चर और स्थितिगत मापदंडों के साथ खिलवाड़ कर सकते हैं?
तकनीकी रूप से, हम दोनों के साथ गड़बड़ कर सकते हैं, लेकिन हमें पर्यावरण चर के साथ गड़बड़ नहीं करनी चाहिए , जबकि हमें अक्सर स्थितीय पैरामीटर प्रदान करना होता है। हम उदाहरण के लिए, एक चर को प्रस्तुत करने के साथ शेल में कमांड चला सकते हैं:
$ hello=world bash -c 'echo $hello'
world
हम केवल export variable=value
शेल या स्क्रिप्ट के भीतर से चर को पर्यावरण में रख सकते हैं । या हम पूरी तरह से खाली वातावरण के साथ एक कमांड चला सकते हैं env -c command arg1 arg2
। हालांकि, आम तौर पर पर्यावरण के साथ खिलवाड़ करने की सिफारिश नहीं की जाती है, विशेष रूप से ऊपरी-केस चर या पहले से मौजूद पर्यावरण चर का ओवरराइटिंग। सूचना है कि एक मानक नहीं है, हालांकि सिफारिश की है।
स्थितीय मापदंडों के लिए, उन्हें सेट करने का तरीका स्पष्ट है, बस उन्हें कमांड में प्रस्तुत करना है, लेकिन उन्हें अन्य बुद्धिमानों को सेट करने के तरीके भी हैं , साथ ही shift
कमांड के माध्यम से उन मापदंडों की सूची को बदलना है ।
अंत में, इन दोनों का उद्देश्य अलग है, और वे एक कारण के लिए मौजूद हैं। मुझे आशा है कि लोगों ने इस उत्तर से कुछ अंतर्दृष्टि प्राप्त की, और इसे पढ़ने में मज़ा आया क्योंकि यह मेरे लिए यह उत्तर लिखना था।
सेट कमांड पर ध्यान दें
set
आदेश है, इसलिए की तरह बर्ताव करता है मैनुअल के अनुसार (बैश पुस्तिका से, जोर जोड़ा):
विकल्पों के बिना, प्रत्येक शेल चर का नाम और मूल्य एक प्रारूप में प्रदर्शित किया जाता है जिसे वर्तमान में सेट किए गए चर को सेट या रीसेट करने के लिए इनपुट के रूप में पुन: उपयोग किया जा सकता है।
दूसरे शब्दों में set
, शेल के लिए विशिष्ट चर को देखते हैं, जिनमें से कुछ पर्यावरण में होते हैं, उदाहरण के लिए HOME
। इसके विपरीत कमांड जैसी env
और printenv
वास्तविक पर्यावरण चर को देखो जिसके साथ एक कमांड चलता है। यह भी देखें इस ।
export 3
बदल नहीं सकते$3
। तुम नहीं कर सकतेunset 3
; और आप$3
एक नए मान का उपयोग नहीं कर सकते3=val
।