शेल चर और पर्यावरण चर के बीच उपयोग में क्या अंतर है?


16

मुझे वास्तव में नहीं पता था कि दो अलग-अलग प्रकार के चर हैं जिन्हें मैं कमांड लाइन से एक्सेस कर सकता हूं। मुझे पता था कि मैं चर घोषित कर सकता हूं:

foo="my dear friends"
bar[0]="one"
bar[1]="two"
bar[2]="three"

या $ साइन के साथ उन्हें एक्सेस करना, जैसे:

echo $foo
echo ${bar[1]}

या इनबिल्ट वैरिएबल्स का उपयोग करना, जैसे:

echo $PWD
PATH=$PATH:"/usr/bin/myProg"

अब, मैंने सुना है कि चर के दो (कम से कम?) प्रकार हैं: शेल चर और पर्यावरण चर।

  • दो अलग-अलग प्रकार होने का उद्देश्य क्या है?
  • मुझे कैसे पता चलेगा कि कौन सा प्रकार एक चर है?
  • हर एक के लिए विशिष्ट उपयोग क्या हैं?


जवाबों:


14

पर्यावरण चर name=valueजोड़े की एक सूची है जो कार्यक्रम (शैल, अनुप्रयोग, डेमन…) जो कुछ भी मौजूद है। वे आम तौर पर बच्चों की प्रक्रियाओं (विरासत fork/ execअनुक्रम द्वारा बनाई गई ) द्वारा विरासत में प्राप्त होते हैं : बच्चों की प्रक्रियाओं को माता-पिता चर की अपनी प्रति मिलती है।

शेल चर केवल एक शेल के संदर्भ में मौजूद हैं। वे केवल उपधाराओं में विरासत में मिले हैं (अर्थात जब शेल बिना execऑपरेशन के कांटा जाता है)। शेल की विशेषताओं के आधार पर, चर न केवल पर्यावरण की तरह सरल तार हो सकते हैं, बल्कि एरे, कम्पाउंड, टाइप किए गए चर जैसे पूर्णांक या फ्लोटिंग पॉइंट आदि भी हो सकते हैं।

जब कोई शेल शुरू होता है, तो उसके माता-पिता से विरासत में मिले सभी पर्यावरण चर भी शेल वेरिएबल बन जाते हैं (जब तक कि वे शेल वेरिएबल्स के रूप में अमान्य नहीं होते हैं और अन्य कोने के मामले जैसे IFSकि कुछ शेल द्वारा रीसेट किए जाते हैं) लेकिन इन विरासत वाले वेरिएबल्स को निर्यात 1 के रूप में टैग किया जाता है । इसका मतलब है कि वे शेल द्वारा निर्धारित संभावित अद्यतन मूल्य वाले बच्चों की प्रक्रियाओं के लिए उपलब्ध रहेंगे। यह भी शेल के तहत बनाए गए चर के साथ मामला है और exportकीवर्ड के साथ निर्यात के रूप में टैग किया गया है ।

सरणी और अन्य जटिल प्रकार के चर तब तक निर्यात नहीं किए जा सकते जब तक कि उनके नाम और मूल्य को name=valueपैटर्न में परिवर्तित नहीं किया जा सकता है , या जब एक शेल विशिष्ट तंत्र जगह में है (जैसे: bashपर्यावरण में निर्यात कार्य और कुछ विदेशी, गैर POSIX गोले जैसे rcऔर esसरणियों का निर्यात कर सकते हैं। )।

इसलिए पर्यावरण चर और शेल चर के बीच मुख्य अंतर उनका दायरा है: पर्यावरण चर वैश्विक हैं जबकि गैर निर्यात शैल चर स्क्रिप्ट के लिए स्थानीय हैं।

यह भी ध्यान दें कि आधुनिक गोले (कम से कम kshऔर bashएक तिहाई शेल चर दायरे) का समर्थन करते हैं। typesetकीवर्ड के साथ फ़ंक्शंस में बनाए गए वेरिएबल्स उस फ़ंक्शन के लिए स्थानीय हैं (जिस तरह से फ़ंक्शन घोषित किया गया है ksh, इस सुविधा को सक्षम / अक्षम करता है , और दृढ़ता व्यवहार के बीच भिन्न होता है bashऔर ksh)। Https://unix.stackexchange.com/a/28349/2594 देखें

1 यह लागू होता है के लिए आधुनिक गोले की तरह ksh, dash, bashऔर इसी तरह की। विरासत बोर्न शेल और गैर बॉर्न सिंटैक्स गोले जैसे cshअलग-अलग व्यवहार हैं।


1
सब कुछ बच्चों की प्रक्रियाओं द्वारा विरासत में मिला है क्योंकि बच्चों को उनके माता-पिता के एक कांटा (एक सटीक प्रतिलिपि) के रूप में बनाया जाता है। पर्यावरण चर के साथ बिंदु यह है कि उन्हें execve()सिस्टम कॉल में पास किया जाता है (आमतौर पर) अन्य कमांड के निष्पादन पर डेटा को बनाए रखने के लिए उपयोग किया जाता है (उसी प्रक्रिया में)।
स्टीफन चेज़लस

सभी पर्यावरण चर शेल शेल के लिए अनुवादित नहीं हैं। केवल वे जो शेल चर नाम के रूप में मान्य हैं (और कुछ अपवादों जैसे IFSकुछ गोले में)।
स्टीफन चेज़लस

गोले पसंद करते हैं rc, esएडहॉक एन्कोडिंग का उपयोग करके सरणियों को निर्यात कर सकते हैं। bashऔर rcपर्यावरण चर (फिर से, एक विशेष एन्कोडिंग का उपयोग करके) का उपयोग करके कार्यों को निर्यात कर सकते हैं।
स्टीफन चेज़लस

में ksh93, typesetकेवल function foo { ...; }सिंटैक्स के साथ घोषित कार्यों में गुंजाइश को प्रतिबंधित करता है , बॉर्न ( foo() cmd) सिंटैक्स के साथ नहीं (और यह अन्य स्थानों की तरह गतिशील स्कोपिंग गतिशील नहीं है)।
स्टीफन चेज़लस

@ स्टीफनचैलेजस समीक्षा के लिए धन्यवाद! आपकी टिप्पणी को ध्यान में रखने के लिए उत्तर को अपडेट किया गया।
08

17

शैल चर

शेल चर वे चर होते हैं जिनका दायरा वर्तमान शेल सत्र में होता है, उदाहरण के लिए एक इंटरैक्टिव शेल सत्र या एक स्क्रिप्ट में।

आप एक अप्रयुक्त नाम के लिए एक मान प्रदान करके एक शेल चर बना सकते हैं:

var="hello"

वर्तमान सत्र में डेटा का ट्रैक रखने के लिए शेल चरों का उपयोग किया जाता है। शेल वेरिएबल्स में आमतौर पर लोअर-केस अक्षरों के साथ नाम होते हैं।

पर्यावरण चर

एक पर्यावरण चर एक शेल चर है जिसे निर्यात किया गया है। इसका मतलब है कि यह एक चर के रूप में दिखाई देगा, न केवल शेल सत्र में जिसने इसे बनाया, बल्कि किसी भी प्रक्रिया के लिए (न केवल गोले) जो उस सत्र से शुरू किए गए हैं।

VAR="hello"  # shell variable created
export VAR   # variable now part of the environment

या

export VAR="hello"

एक बार शेल वैरिएबल एक्सपोर्ट हो जाने के बाद, यह तब तक एक्सपोर्ट होता रहता है, जब तक कि यह अनसेट नहीं हो जाता है, या जब तक इसकी "एक्सपोर्ट प्रॉपर्टी" (साथ export -nमें bash) नहीं हट जाती है , इसलिए आमतौर पर इसे री-एक्सपोर्ट करने की कोई जरूरत नहीं है। एक चर को हटाने के साथ unsetइसे हटाना (कोई फर्क नहीं पड़ता कि यह पर्यावरण चर है या नहीं)।

bashपर्यावरण के चर बनने के लिए और अन्य खोलों में ऐरे और एसोसिएटिव हैश का निर्यात नहीं किया जा सकता है। पर्यावरण चर सरल चर होने चाहिए जिनके मूल्य तार होते हैं, और उनके पास अक्सर ऊपरी-अक्षर वाले नाम होते हैं।

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

एक प्रक्रिया में पर्यावरण चर का संग्रह अक्सर "प्रक्रिया का वातावरण" के रूप में जाना जाता है। प्रत्येक प्रक्रिया का अपना वातावरण होता है।

पर्यावरण चर केवल "अग्रेषित" किया जा सकता है, अर्थात एक बच्चे की प्रक्रिया अपनी मूल प्रक्रिया में पर्यावरण चर को कभी नहीं बदल सकती है, और इसे शुरू करने पर एक बच्चे की प्रक्रिया के लिए पर्यावरण स्थापित करने के अलावा, एक माता पिता की प्रक्रिया मौजूदा पर्यावरण को नहीं बदल सकती है बच्चे की प्रक्रिया।

पर्यावरण चर को env(बिना किसी तर्क के) सूचीबद्ध किया जा सकता है । इसके अलावा, वे शेल सत्र में गैर-निर्यात शेल चर के समान दिखाई देते हैं। यह शेल के लिए थोड़ा विशेष है क्योंकि अधिकांश अन्य प्रोग्रामिंग भाषाएं आमतौर पर पर्यावरण चर (नीचे देखें) के साथ "साधारण" वैरिएबल को रोकती नहीं हैं।

env वर्तमान सत्र में उन्हें सेट किए बिना प्रक्रिया के वातावरण में एक या कई पर्यावरण चर के मूल्यों को निर्धारित करने के लिए भी उपयोग किया जा सकता है:

env CC=clang CXX=clang++ make

यह makeपर्यावरण वैरिएबल से शुरू होता CCहै जो वैल्यू पर सेट होता है clangऔर से CXXसेट होता है clang++

यह एक प्रक्रिया के लिए पर्यावरण को साफ करने के लिए भी इस्तेमाल किया जा सकता है:

env -i bash

यह शुरू होता है bashलेकिन वर्तमान वातावरण को नई bashप्रक्रिया में स्थानांतरित नहीं करता है (इसके पास अभी भी पर्यावरण चर होंगे क्योंकि यह अपनी शेल प्रारंभिक लिपियों से नए बनाता है)।

अंतर का उदाहरण

$ var="hello"   # create shell variable "var"
$ bash          # start _new_ bash session
$ echo "$var"   # no output
$ exit          # back to original shell session
$ echo "$var"   # "hello" is outputted
$ unset var     # remove variable

$ export VAR="hello"  # create environment variable "VAR"
$ bash
$ echo "$VAR"         # "hello" is outputted since it's exported
$ exit                # back to original shell session
$ unset VAR           # remove variable

$ ( export VAR="hello"; echo "$VAR" )  # set env. var "VAR" to "hello" in subshell and echo it
$ echo "$VAR"         # no output since a subshell has its own environment

अन्य भाषाएँ

अधिकांश प्रोग्रामिंग भाषाओं में लाइब्रेरी फ़ंक्शन हैं जो पर्यावरण चर को प्राप्त करने और स्थापित करने की अनुमति देता है। ध्यान दें कि चूंकि पर्यावरण चर को एक साधारण कुंजी-मूल्य संबंध के रूप में संग्रहीत किया जाता है, वे आमतौर पर भाषा के "चर" नहीं होते हैं। एक प्रोग्राम एक कुंजी (पर्यावरण चर का नाम) के अनुरूप मूल्य (जो हमेशा एक चरित्र स्ट्रिंग है) प्राप्त कर सकता है, लेकिन फिर इसे एक पूर्णांक में बदलना होगा या जो भी डेटा प्रकार भाषा के मूल्य का अनुमान है।

सी में, वातावरण चर का उपयोग कर पहुँचा जा सकता है getenv(), setenv(), putenv()और unsetenv()। इन दिनचर्या के साथ बनाए गए चर को सी प्रोग्राम शुरू होने वाली किसी भी प्रक्रिया द्वारा उसी तरह विरासत में मिला है।

अन्य भाषाओं में एक ही चीज़ को पूरा करने के लिए विशेष डेटा संरचनाएं हो सकती हैं, जैसे %ENVपर्ल में हैश, या ENVIRONअधिकांश कार्यान्वयन में सहयोगी सरणी awk


thx, शानदार ढंग से स्पष्ट व्याख्या। इसलिए पर्यावरण एक बड़े क्षेत्र की तरह है जिसमें अन्य कार्यक्रम पर्यावरण के प्रत्येक चर को देख सकते हैं और देख सकते हैं। कुछ कार्यक्रमों के अपने निजी चर हैं, केवल वे स्वयं उन्हें देख सकते हैं, जैसे शेल। लेकिन निजी चर बनाने के लिए एक तंत्र है जिसे "निर्यात" कहा जाता है। यदि यह ठीक समझा जाता है, केवल एक चीज से मुझे यकीन नहीं है कि क्या एक ही समय में एक से अधिक वातावरण हो सकते हैं?
शार्क shar

@ क्षारक प्रत्येक चलने की प्रक्रिया का अपना वातावरण होता है। यह वातावरण उस प्रक्रिया से विरासत में मिला है जिसने इसे शुरू किया था। विभिन्न प्रक्रियाओं के वातावरण के बीच कभी भी "क्रॉस-टॉक" नहीं होता है। एक प्रक्रिया में पर्यावरण चर को बदलने का एकमात्र तरीका प्रक्रिया के लिए ही है जो इसे संशोधित करता है।
Kusalananda

मेरी समझ के लिए clxfing। प्रत्येक मछली अपने स्वयं के मछली के कटोरे के अंदर। उन प्रक्रियाओं के बारे में कैसे जो अन्य प्रक्रियाओं को स्पॉन करती हैं? क्या प्रक्रियाएँ और उनकी बाल-प्रक्रियाएँ सभी एक ही वातावरण में होती हैं या प्रत्येक की अपनी होती है?
शार्क

1
@ अक्षरक अधिकांश भाषाओं में पुस्तकालय कार्य हैं जो पर्यावरण चर को प्राप्त करने और स्थापित करने की अनुमति देते हैं। सी में, इस के साथ किया जाता getenv(), setenv(), putenv()और unsetenv()। इन दिनचर्या के साथ बनाए गए चर को सी प्रोग्राम शुरू होने वाली किसी भी प्रक्रिया द्वारा उसी तरह विरासत में मिला है। अन्य भाषाओं में एक ही चीज़ के लिए विशेष डेटा संरचनाएं हो सकती हैं, जैसे %ENVपर्ल में।
Kusalananda

1
एफडब्ल्यूआईडब्ल्यू: exec*()कार्यों के परिवार को निष्पादित की जाने वाली प्रक्रिया के लिए वातावरण भी निर्धारित किया जा सकता है।
सातु कटुरा

5

शेल वेरिएबल को डुप्लिकेट करना मुश्किल है।

$ FOO=bar
$ FOO=zot
$ echo $FOO
zot
$ 

पर्यावरण चर को दोहराया जा सकता है; वे केवल एक सूची हैं, और एक सूची में डुप्लिकेट प्रविष्टियाँ हो सकती हैं। यहां envdup.cबस इतना ही करना है।

#include <err.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

extern char **environ;

int main(int argc, char *argv[]) {
    char **newenv;
    int envcount = 0;

    if (argc < 2) errx(64, "Usage: envdup command [args ..]");

    newenv = environ;
    while (*newenv++ != NULL) envcount++;

    newenv = malloc(sizeof(char *) * (envcount + 3));
    if (newenv == NULL) err(1, "malloc failed");
    memcpy(newenv, environ, sizeof(char *) * envcount);
    newenv[envcount]   = "FOO=bar";
    newenv[envcount+1] = "FOO=zot";
    newenv[envcount+2] = NULL;

    environ = newenv;
    argv++;
    execvp(*argv, argv);
    err(1, "exec failed '%s'", *argv);
}

जिसे हम बता सकते हैं और बता सकते हैं कि पर्यावरण के चर सेट हैं, हमें दिखाने के लिए envdupचलाएं env...

$ make envdup
cc     envdup.c   -o envdup
$ unset FOO
$ ./envdup env | grep FOO
FOO=bar
FOO=zot
$ 

यह शायद केवल बग या अन्य विषमताओं को खोजने के लिए उपयोगी है कि प्रोग्राम कितनी अच्छी तरह से संभालते हैं **environ

$ unset FOO
$ ./envdup perl -e 'exec "env"' | grep FOO
FOO=bar
$ ./envdup python3 -c 'import os;os.execvp("env",["env"])' | grep FOO
FOO=bar
FOO=zot
$ 

ऐसा लगता है कि यहाँ पाइथन 3.6 नेत्रहीन डुप्लिकेट (एक टपका हुआ अमूर्त) के साथ गुजरता है, जबकि पर्ल 5.24 नहीं है। गोले के बारे में कैसे?

$ ./envdup bash -c 'echo $FOO; exec env' | egrep 'bar|zot'
zot
FOO=zot
$ ./envdup zsh -c 'echo $FOO; exec env' | egrep 'bar|zot' 
bar
FOO=bar
$ 

गोश, क्या होता है यदि sudoकेवल पहले पर्यावरण प्रविष्टि को पवित्र करता है लेकिन फिर bashदूसरे के साथ चलता है? नमस्कार PATHया LD_RUN_PATHशोषण। क्या आपका sudo(और बाकी सब कुछ ?) उस छेद के लिए तैयार है ? सुरक्षा कारनामे न तो "एक विशिष्ट अंतर" हैं और न ही कॉलिंग प्रोग्राम में "बग" हैं।


1
यह सच है लेकिन एक वास्तविक अंतर है और यकीनन डुप्लिकेट चर को सेट करने वाले प्रोग्राम का एक बग है।
जूलियाग्रे


0

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

env –कमांड आपको वर्तमान परिवेश को संशोधित किए बिना कस्टम वातावरण में एक और कार्यक्रम चलाने की अनुमति देता है। जब एक तर्क के बिना उपयोग किया जाता है तो यह वर्तमान पर्यावरण चर की एक सूची मुद्रित करेगा। printenv –कमांड सभी या निर्दिष्ट पर्यावरण चर प्रिंट करता है। set –कमांड सेट या चर शेल सेट करता है। जब एक तर्क के बिना उपयोग किया जाता है तो यह पर्यावरण और शेल चर, और शेल फ़ंक्शन सहित सभी चर की एक सूची मुद्रित करेगा। unset –कमांड शेल और एनवायरनमेंट वेरिएबल्स को डिलीट करता है। export –आदेश वातावरण चर सेट करता है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.