किसी प्रक्रिया के पर्यावरण चर को कैसे पढ़ें


43

लिनक्स /proc/<pid>/environअपडेट नहीं करता है (जैसा कि मैं इसे समझता हूं, फ़ाइल में प्रक्रिया का प्रारंभिक वातावरण होता है)।

मैं एक प्रक्रिया के वर्तमान वातावरण को कैसे पढ़ सकता हूं ?

जवाबों:


20

/proc/$pid/environयदि प्रक्रिया अपने स्वयं के वातावरण को बदलती है तो अद्यतन करता है। लेकिन कई कार्यक्रमों है, क्योंकि यह एक सा व्यर्थ है अपने स्वयं के माहौल बदल रहा परेशान नहीं है: एक कार्यक्रम के माहौल न केवल के माध्यम से, सामान्य चैनलों के माध्यम से दिखाई दे रहा है /procऔर ps, और यहां तक कि नहीं हर यूनिक्स संस्करण सुविधा के इस प्रकार है, तो अनुप्रयोगों भरोसा नहीं करते इस पर।

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


इसलिए, प्रभावी रूप से इस प्रक्रिया का उपयोग करने का कोई तरीका नहीं है '* envp (पर्यावरण सेटिंग्स के लिए संकेत का सरणी)। @ जील्स, क्या आप यह दिखा सकते हैं कि क्या डिबगर संलग्न करना और पर्यावरण सेटिंग्स पर पॉइंटर्स की सरणी को पढ़ना संभव है।
निखिल मुल्ले

2
@ निखिल ज़रूर, यह है। लेकिन सिर्फ इसलिए कि आप PATH=fooएक शेल में लिखते हैं इसका मतलब यह नहीं है कि शेल संशोधित करने जा रहा है *envp। कुछ गोले में, जो केवल एक आंतरिक डेटा संरचना को अद्यतन करता है, और यह बाहरी प्रोग्राम निष्पादन कोड है जो अपडेट करता है *envp। को देखो assign_in_envमें variables.cबैश स्रोत में, उदाहरण के लिए।
गाइल्स का SO-

9
@ गिल्स: यह उत्तर सबसे भ्रामक है (-1)। प्रक्रिया के ढेर से / proc / $ $ / environ में पर्यावरण पढ़ा जाता है। Fs / proc / base.c देखें। यह प्रारंभिक वातावरण है। यह कभी अद्यतन नहीं होता है और वास्तव में यह नहीं हो सकता है। लिबास सेटेनव का उपयोग करने वाला वातावरण ढेर पर आवंटित किया जाता है और स्टैक में पर्यावरण की सामग्री के साथ आरम्भ किया जाता है। यदि प्रक्रिया libc को कॉल करती है forkतो libc sys_forkबाल प्रक्रिया के लिए ढेर आवंटित वातावरण का उपयोग करके कॉल करता है।
जोनाथन बेन-अब्राहम

7
@ JonathanBen-Avraham आप सही हैं कि प्रारंभिक वातावरण किसी भी शेल में अपडेट नहीं किया गया है। हालाँकि, यह क्षेत्र केवल लिनक्स के तहत पढ़ा नहीं जाता है, मैंने उन कार्यक्रमों का सामना किया है जो अपनी स्थिति की रिपोर्ट करने के लिए इसका उपयोग करते हैं (स्थिति रिपोर्ट के माध्यम argvसे अधिक सामान्य हैं, लेकिन दोनों मौजूद हैं)।
गिल्स एसओ- बुराई को रोकें '

39

आप किसी प्रक्रिया के प्रारंभिक वातावरण को पढ़ सकते हैं /proc/<pid>/environ

यदि कोई प्रक्रिया अपना वातावरण बदलती है, तो पर्यावरण को पढ़ने के लिए आपके पास प्रक्रिया के लिए प्रतीक तालिका होनी चाहिए और वैश्विक चर से पर्यावरण को पढ़ने के ptraceलिए सिस्टम कॉल (उदाहरण के लिए उपयोग करके gdb) का उपयोग करें char **__environ। चल रहे लिनक्स प्रक्रिया से किसी भी चर का मूल्य प्राप्त करने का कोई अन्य तरीका नहीं है।

यही जवाब है। अब कुछ नोटों के लिए।

उपरोक्त मानता है कि प्रक्रिया POSIX अनुपालन है, जिसका अर्थ है कि प्रक्रिया वैश्विक वातावरण का उपयोग करते char **__environहुए Ref Spec में निर्दिष्ट के रूप में अपने वातावरण का प्रबंधन करती है ।

एक प्रक्रिया के लिए प्रारंभिक वातावरण प्रक्रिया के ढेर पर एक निश्चित लंबाई के बफर में प्रक्रिया को पारित किया जाता है। (सामान्य तंत्र जो ऐसा करता है linux//fs/exec.c:do_execve_common(...)।) चूंकि बफर के आकार की गणना प्रारंभिक वातावरण के लिए आवश्यक आकार से अधिक नहीं है, आप मौजूदा चर को मिटाए बिना या स्टैक को नष्ट किए बिना नए चर नहीं जोड़ सकते। इसलिए, किसी प्रक्रिया के वातावरण में बदलाव की अनुमति देने के लिए कोई भी उचित योजना ढेर का उपयोग करेगी, जहां मनमाने आकार में मेमोरी आवंटित की जा सकती है और उसे मुक्त किया जा सकता है, जो कि GNU libc( glibc) आपके लिए करता है।

यदि प्रक्रिया का उपयोग करता है glibc, तो यह POSIX आज्ञाकारी है, Glibc __environमें घोषित होने के साथ एक पॉइंटर को मेमोरी के साथ glibc//posix/environ.cआरंभ __environकरता है कि यह mallocप्रक्रिया के ढेर से है, फिर स्टैक से प्रारंभिक वातावरण को इस ढेर क्षेत्र में कॉपी करता है। हर बार जब प्रक्रिया setenvफ़ंक्शन का उपयोग करती है, तो glibcवह reallocउस क्षेत्र के आकार को समायोजित करने के लिए करता है __environजो नए मूल्य या चर को समायोजित करने के लिए इंगित करता है। (आप glibc स्रोत कोड के साथ डाउनलोड कर सकते हैं git clone git://sourceware.org/git/glibc.git glibc)। वास्तव में तंत्र को समझने के लिए आपको हर्ड कोड को भी पढ़ना होगा hurd//init/init.c:frob_kernel_process()(git क्लोन क्लोन git: //git.sv.gnu.org/hurd/hurd.git हर्ड)।

अब यदि नई प्रक्रिया केवल forkएड है, इसके बाद execस्टैक को ओवरराइट किए बिना , तो तर्क और पर्यावरण की नकल जादू में किया जाता है linux//kernel/fork.c:do_fork(...), जहां copy_processरूटीन कॉल dup_task_structजो कॉल करके नई प्रक्रिया के स्टैक को आवंटित करता है alloc_thread_info_node, जो नई प्रक्रिया का उपयोग करके कॉल setup_thread_stack( linux//include/linux/sched.h) करता है alloc_thread_info_node

अंत में, POSIX __environसम्मेलन एक उपयोगकर्ता-स्थान सम्मेलन है। लिनक्स कर्नेल में इसका किसी भी चीज़ से कोई संबंध नहीं है। आप उपयोग glibcकिए बिना और __environवैश्विक के बिना एक यूजरस्पेस प्रोग्राम लिख सकते हैं और फिर आपके द्वारा पसंद किए जाने वाले पर्यावरण चर का प्रबंधन कर सकते हैं। ऐसा करने के लिए कोई आपको गिरफ्तार नहीं करेगा, लेकिन आपको अपने स्वयं के पर्यावरण प्रबंधन कार्यों ( setenv/ getenv) और अपने स्वयं के रैपर के लिए लिखना होगा sys_execऔर यह संभावना है कि कोई भी यह अनुमान लगाने में सक्षम नहीं होगा कि आप अपने वातावरण में बदलाव कहां डालते हैं।


/proc/[pid]/दिखाई देने वाली फ़ाइलों में से कई में एक अजीब एन्कोडिंग है (किसी और को क्या और क्यों पता हो सकता है)। मेरे लिए, बस cat environवास्तव में पढ़ने के लिए प्रारूप में पर्यावरण चर प्रिंट आउट होगा। cat environ | stringsमेरे लिए यह हल किया।
रेट्रोकेकर

@retrohacker यह एक अधिक मजबूत समाधान प्रदान करता है: askubuntu.com/questions/978711/…
फ्रैंक कलीस

20

इसे अपडेट किया जाता है और जब प्रक्रिया अपने पर्यावरण चर को प्राप्त / हटा देती है। क्या आपके पास एक संदर्भ है जो बताता है कि environफ़ाइल प्रक्रिया में प्रक्रिया के लिए अद्यतन नहीं की गई है।

xargs --null --max-args=1 echo < /proc/self/environ

या

xargs --null --max-args=1 echo < /proc/<pid>/environ

या

ps e -p <pid>

ऊपर psआउटपुट प्रारूप में प्रक्रिया के पर्यावरण चर को प्रिंट करेगा , पर्यावरण चर को सूची के रूप में देखने के लिए पाठ-प्रसंस्करण (पार्सिंग / फ़िल्टरिंग) आवश्यक है।

सोलारिस (पूछा नहीं गया, लेकिन संदर्भ के लिए मैं यहां पोस्ट करूंगा):

/usr/ucb/ps -wwwe <pid>

या

pargs -e <pid> 

संपादित करें: / proc / pid / environ अपडेट नहीं है! मुझे सही साबित होना है। सत्यापन की प्रक्रिया नीचे है। हालाँकि, जिन बच्चों से प्रक्रिया कांटेक्ट होती है, वे प्रक्रिया पर्यावरण चर का वारिस कर देते हैं और यह उनके संबंधित / प्रोक / से / फ़िनिश फ़ाइल में दिखाई देता है। (स्ट्रिंग्स का उपयोग करें)

शेल में: यहाँ xargs एक चाइल्ड प्रोसेस है और इसलिए पर्यावरण वेरिएबल को इनहेरिट करता है और इसकी /proc/self/environफाइल में भी दिखाई देता है ।

[centos@centos t]$ printenv  | grep MASK
[centos@centos t]$ export MASK=NIKHIL
[centos@centos t]$ printenv  | grep MASK
MASK=NIKHIL
[centos@centos t]$ xargs --null --max-args=1 echo < /proc/self/environ  | grep MASK
MASK=NIKHIL
[centos@centos t]$ unset MASK
[centos@centos t]$ printenv  | grep MASK
[centos@centos t]$ xargs --null --max-args=1 echo < /proc/self/environ  | grep MASK
[centos@centos t]$

अन्य सत्र से इसकी जाँच करना, जहाँ टर्मिनल / सत्र शेल की बाल प्रक्रिया नहीं है जहाँ पर्यावरण चर सेट किया गया है।

एक ही मेजबान पर एक और टर्मिनल / सत्र से सत्यापन:

टर्मिनल 1 :: ध्यान दें कि प्रिंटेन फोर्कलिफ्ट है और बैश की एक बच्चे की प्रक्रिया है और इसलिए यह अपनी स्वयं की फाइल को पढ़ता है।

[centos@centos t]$ echo $$
2610
[centos@centos t]$ export SPIDEY=NIKHIL
[centos@centos t]$ printenv | grep SPIDEY
SPIDEY=NIKHIL
[centos@centos t]$ 

टर्मिनल 2: एक ही मेजबान पर - इसे उसी शेल में लॉन्च न करें जहां उपरोक्त चर सेट किया गया था, टर्मिनल को अलग से लॉन्च करें।

[centos@centos ~]$ echo $$
4436
[centos@centos ~]$ xargs --null --max-args=1 echo < /proc/self/environ | grep -i spidey
[centos@centos ~]$ strings -f /proc/2610/environ | grep -i spidey
[centos@centos ~]$ xargs --null --max-args=1 echo < /proc/2610/environ | grep -i spidey
[centos@centos ~]$ 

1
मैं export foo=barएक बैश सत्र (pid xxxx) cat /proc/xxxx/environ | tr \\0 \\nमें करता हूं, फिर दूसरे बैश सत्र में करता हूं और मुझे दिखाई नहीं देता foo

मैंने शेल के भीतर एक ही प्रक्रिया की जाँच करते हुए एक उदाहरण के साथ उपरोक्त उत्तर को अपडेट किया।
निखिल मुल्ले

तुम सही हो। मुझे सही साबित होना है। धन्यवाद। मुझे अब उपयोगकर्ता प्रक्रिया समूह के साथ एक अलग प्रक्रिया के पर्यावरण चर की जांच करने के लिए अपने मैनुअल को पढ़ना और पढ़ना होगा।
निखिल मुल्ले

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

मुझे उम्मीद है कि @ गिल्स इस पर अपना कुछ टार्च की रोशनी
फेंकेंगे

7

वैसे लेखक के वास्तविक इरादों के साथ निम्नलिखित का संबंध नहीं है, लेकिन यदि आप वास्तव में "READ" करना चाहते हैं /proc/<pid>/environ, तो आप कोशिश कर सकते हैं

strings /proc/<pid>/environ

जो इससे बेहतर है cat


1
के लिए +1 strings। इसे सरल रखें।
एड रान्डल

@EdRandall से सहमत हों, यह आसान तरीका बनाम की तरह लगता है xargs --null
प्रति लंडबर्ग

"फ़ाइल" को समाप्त कर दिया गया है, नई-लाइन और सामान्य टूल के साथ नल को फिर से काम करें (सामान्य कैविट्स के साथ), जैसे:tr '\0' '\n' < /proc/$$/environ | ...
थोर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.