2012-04-03 19 views
8

का उपयोग कर पर्यावरण चर प्राप्त करें यहां मैंने एक सी प्रोग्राम लिखा है जो कॉल का उपयोग कर hi.sh फ़ाइल निष्पादित करता है।सी कोड

यहाँ मैं इस्तेमाल किया . ./hi.sh तो मैं एक ही खोल में इस स्क्रिप्ट को निष्पादित और फिर getenv फ़ंक्शन का उपयोग वातावरण चर प्राप्त करने की कोशिश करना चाहते हैं, लेकिन यहाँ मैं मैं क्या उम्मीद से अलग उत्पादन हो रही है।

hi.sh फ़ाइल

export TEST=10 
return 

मतलब जब मैं सिस्टम कॉल का उपयोग कर इस hi.sh फ़ाइल को चलाने में शामिल है, अपने export TEST ही खोल में 10 के लिए मूल्य तय करता है। इसके बाद, मैं इस चर मूल्य को प्राप्त करने का प्रयास कर रहा हूं लेकिन इसके NULL मान दिए गए हैं।

और यदि मैं . ./hi.sh जैसे कंसोल से मैन्युअल रूप से इस स्क्रिप्ट को चलाता हूं तो यह ठीक काम करता है और मुझे getenv("TEST") फ़ंक्शन का उपयोग करके TEST का 10 मान मिलता है।

कोड:

#include <stdio.h> 
int main() 
{ 
    system(". ./hi.sh"); 
    char *errcode; 
    char *env = "TEST"; 
    int errCode;  
    errcode = getenv(env); 
    printf("Value is = %s\n",errcode); 
    if (errcode != NULL) { 
     errCode =atoi(errcode); 
     printf("Value is = %d\n",errCode); 
    } 
} 

उत्पादन:

Value is = (null) 

मैं कैसे कार्यक्रम खोल में टेस्ट चर निर्यात कर सकते हैं? यदि system() विभिन्न शैल में कमांड निष्पादित करता है तो मैं एक पर्यावरण चर प्राप्त करने के लिए सी प्रोग्राम कोड का उपयोग कैसे कर सकता हूं जिसे system() कॉल के माध्यम से बुलाए गए खोल द्वारा निर्यात किया जाता है?

उत्तर

7

सामान्य रूप से, मैन पेज यह समझाता है, लेकिन आपको इसे बहुत सावधानी से पढ़ने की आवश्यकता है।

DESCRIPTION 
     system() executes a command specified in command by calling /bin/sh -c 
     command, and returns after the command has been completed. During exe‐ 
     cution of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT 
     will be ignored. 

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

+0

तो मैं इस लक्ष्य को कैसे प्राप्त कर सकता हूं? – user1089679

+0

मैं प्रोग्राम शैल में टेस्ट वैरिएबल कैसे निर्यात कर सकता हूं? – user1089679

+2

@ उपयोगकर्ता 1089679 अपने सी प्रोग्राम को चलाने से पहले अपनी स्क्रिप्ट (पर्यावरण स्थापित करें) स्रोत करें। इस प्रकार पर्यावरण चर का उपयोग करने के लिए डिजाइन किए गए थे। –

0

आप setenv() (जो system() तो चुपचाप बच्चे प्रक्रियाओं के लिए पर से गुजरता है, या स्पष्ट रूप से fork() और execve() का उपयोग कर खोल स्क्रिप्ट को चलाने के लिए द्वारा चर पारित का उपयोग कर अपनी खुद की प्रक्रिया में वातावरण चर सेट कर सकते हैं या तो।

+0

आपके उत्तर के लिए धन्यवाद। लेकिन मुझे सिस्टम कॉल का उपयोग करके खोल स्क्रिप्ट को कॉल करना है और स्क्रिप्ट से पर्यावरण चर सेट करना आवश्यक है। इसके बाद मैं खोल – user1089679

+2

से पर्यावरण चर प्राप्त करना चाहता हूं यह संभव नहीं है। वैरिएबल केवल नव निर्मित प्रक्रियाओं को पारित किया जा सकता है, न कि मूल प्रक्रिया पर वापस। आपकी स्क्रिप्ट को कुछ आउटपुट उत्पन्न करना चाहिए, जिसे आप 'system()' के बजाय 'popen() 'का उपयोग कर पुनर्प्राप्त कर सकते हैं। –

9

बच्चे प्रक्रिया सीधे माता पिता प्रक्रिया के वातावरण दृष्टिकोण system() और getenv() का उपयोग कर विफल बर्बाद है, इसलिए सेट कर सकते हैं नहीं।।

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

मान लीजिए कि hi.sh$ENV1 और $ENV2 सेट करता है। आप अपने प्रोग्राम के मान सेट करने के लिए popen() का उपयोग कर सकते हैं, और अपने प्रोग्राम के वातावरण को सेट करने के लिए setenv() का उपयोग कर सकते हैं।रूपरेखा में:

FILE *fp = popen(". ./hi.sh; echo ENV1=$ENV1; echo ENV2=$ENV2", "r"); 

while (fgets(buffer, sizeof(buffer), fp) != 0) 
{ 
    ...split the buffer into env_name, env_value... 
    setenv(env_name, env_value); 
} 

pclose(fp); 

ध्यान दें कि मैंने प्रतिबिंबित जानकारी में परिवर्तनीय नाम शामिल किया है; यह जीवन को सरल बनाता है। यदि चर की आपकी सूची अनावश्यक हो जाती है, तो हो सकता है कि आप संपूर्ण वातावरण प्राप्त करने के लिए ". ./hi.sh; env" चलाएं, और फिर प्रत्येक पंक्ति को पढ़ें और अपनी अंतर्निहित सूची से बाहर काम करें चाहे वह एक परिवर्तनीय सेटिंग है जिसका आप उपयोग करना चाहते हैं या नहीं। या यदि आप इसे प्रसन्न करते हैं, तो आप बस अपना पूरा वातावरण फिर से सेट कर सकते हैं। आपको यह जांचना चाहिए कि setenv() फ़ंक्शन सफल हुआ (यह सफल होने पर शून्य लौटाता है)। आपको यह भी जांचना चाहिए कि popen() सफल रहा था (fp != 0)। इस संदर्भ में, आप को वैरिएबल नाम से मूल्य से अलग करने के लिए शायद strtok() का उपयोग कर सकते हैं; यह = पर एक अशक्त बाइट tramples, आप एक अशक्त दे नाम और एक अशक्त समाप्त मूल्य समाप्त:

char *env_name = strtok(buffer, "="); 
    char *env_value = buffer + strlen(env_name) + 1; 
    if (setenv(env_name, env_value) != 0) 
     ...report trouble... 
1

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

एक अपरीक्षित उदाहरण:

execl("/bin/sh", "-c", ". ./hi.sh; exec ./a.out --envset", NULL); 

आप के साथ जो कुछ भी वास्तविक प्रोग्राम का नाम है a.out को बदलने के लिए की आवश्यकता होगी। आप शायद इसे argv [0] से निकालना चाहते हैं और बाकी argv सरणी भी पास कर सकते हैं। लेकिन आपको तर्क तर्क के रूप में काम करने के लिए तर्कों को दोबारा सुधारना है, इसलिए उन्हें आवश्यकतानुसार उद्धृत करने की आवश्यकता है, आदि