क्या शेल स्क्रिप्ट के लिए यह जानने का कोई तरीका है कि किस प्रोग्राम ने इसे निष्पादित किया है?


13

* निक्स दुनिया में, शेल स्क्रिप्ट के लिए एक तरीका है जिसके बारे में जानकारी है कि किस कार्यक्रम ने इसे निष्पादित किया है?


उदाहरण:

/path/to/script1 /path/to/script_xyz

इस काल्पनिक परिदृश्य में, script_xyzपथ की जानकारी होगी ( /path/to/script1)

या

प्रक्रिया पीआईडी

संस्था ने इसे निष्पादित किया है।

नोट: मैं विभिन्न समाधानों और दृष्टिकोणों के बारे में उत्सुक हूं, मुझे वास्तव में यह संभव होने की उम्मीद नहीं है


3
आपका विषय पूछता है कि किस प्रोग्राम ने स्क्रिप्ट निष्पादित की है। लेकिन आपका वास्तविक प्रश्न स्क्रिप्ट की व्याख्या के लिए पूछ रहा है । वास्तव में आप दोनों में से कौन सा सवाल है?
कैस्परल्ड

@kasperd आप सही हैं। प्रश्न कार्यक्रम के बारे में था, लेकिन यह वास्तव में दुभाषिया है। इसलिए मुझे लग रहा था कि यह पहली बार में संभव नहीं है।
मिलोस Milakonović

जवाबों:


23

प्रक्रिया फोर्किंग और निष्पादन के बीच अक्सर भ्रम होता है।

जब आप एक bashशेल के संकेत पर करते हैं ।

$ sh -c 'exec env ps'

P1 जारी करने वाली प्रक्रिया, जो $वर्तमान में bashकोड चला रही है । यह bashकोड एक नई प्रक्रिया पी 2 की मांग /bin/shकरता है /usr/bin/env, जो तब निष्पादित होता है, जो फिर निष्पादित होता है /bin/ps

तो P2 बदले में मार डाला गया है के कोड bash, sh, envऔर ps

ps(या किसी अन्य कमांड जैसे स्क्रिप्ट का उपयोग हम यहां करेंगे) यह जानने का कोई तरीका नहीं है कि इसे envकमांड द्वारा निष्पादित किया गया है ।

सभी यह पता लगा सकते हैं कि इसकी मूल प्रक्रिया आईडी क्या है, जो कि इस मामले में पी 1 होगी या 1यदि पी 1 अंतराल में या लिनक्स में किसी अन्य प्रक्रिया में मृत्यु हो गई है जिसे इसके बजाय एक उप-प्रलेखक के रूप में नामित किया गया है 1

फिर यह सिस्टम को इस आदेश के लिए क्वेरी कर सकता है कि वर्तमान में क्या प्रक्रिया चल रही है (जैसे readlink /proc/<pid>/exeलिनक्स पर) या क्या तर्क जहां अंतिम कमांड के लिए पारित किया गया (जैसे ps -o args= -p <pid>)।

यदि आप चाहते हैं कि आपकी स्क्रिप्ट यह जाने कि इसे क्या कहा गया है, तो एक विश्वसनीय तरीका यह होगा कि हमलावर इसे बताए। उदाहरण के लिए एक पर्यावरण चर के माध्यम से किया जा सकता है। उदाहरण के लिए script1इस प्रकार लिखा जा सकता है:

#! /bin/sh -
INVOKER=$0 script2 &

और script2:

#! /bin/sh -
printf '%s\n' "I was invoked by $INVOKER"
# and in this case, we'll probably find the parent process is 1
# (if not now, at least one second later) as script1 exited just after
# invoking script2:
ps -fp "$$"
sleep 1
ps -fp "$$"
exit

$INVOKERहोगा ( आम तौर पर ) के लिए एक रास्ता होता है script1। कुछ मामलों में, हालांकि यह एक सापेक्ष पथ हो सकता है, और यह पथ उस समय की वर्तमान कार्यशील निर्देशिका के सापेक्ष होगा जो script1प्रारंभ हुई थी। तो अगर script1कॉल करने से पहले वर्तमान कार्यशील निर्देशिका बदलता है script2, script2क्या यह कहा जाता है के रूप में गलत जानकारी मिल जाएगी। तो यह सुनिश्चित करना बेहतर हो सकता है कि $INVOKERइसमें एक पूर्ण पथ (अधिमानतः बेसन रखने की तरह) होता है जैसे script1कि:

#! /bin/sh -
mypath=$(
  mydir=$(dirname -- "$0") &&
  cd -P -- "$mydir" &&
  pwd -P) && mypath=$mypath/$(basename -- "$0") || mypath=$0

... some code possibly changing the current working directory
INVOKER=$mypath script2

POSIX गोले में, $PPIDउस प्रक्रिया के माता-पिता का पिंड सम्‍मिलित होगा , जो उस शेल आरंभीकरण के समय शेल को निष्पादित करता है। उसके बाद, जैसा कि ऊपर देखा गया है, अगर आईडी की प्रक्रिया $PPIDमर जाती है , तो मूल प्रक्रिया बदल सकती है।

zshमें zsh/systemमॉड्यूल, क्वेरी कर सकता है वर्तमान के साथ वर्तमान (उप) खोल के माता-पिता पीआईडी $sysparams[ppid]। POSIX गोले में, आप उस प्रक्रिया का वर्तमान ppid प्राप्त कर सकते हैं जिसने दुभाषिया को निष्पादित किया है (यह मानते हुए कि यह अभी भी चल रहा है ps -o ppid= -p "$$"। इसके साथ bash, आप वर्तमान (उप) शेल के pidid के साथ प्राप्त कर सकते हैं ps -o ppid= -p "$BASHPID"


8

हां, एक कार्यक्रम यह जान सकता है कि इसका जनक कौन है।

समझाने के लिए, आइए दो बैश स्क्रिप्ट बनाएं। पहला पीआईडी ​​अपनी रिपोर्ट करता है और दूसरा स्क्रिप्ट शुरू करता है:

$ cat s1.sh
#!/bin/bash
echo s1=$$
bash s2.sh

दूसरी स्क्रिप्ट इसकी प्रक्रिया आईडी, उसके माता-पिता की पीआईडी ​​और माता-पिता को चलाने के लिए उपयोग की जाने वाली कमांड लाइन की रिपोर्ट करती है:

$ cat s2.sh
#!/bin/bash
echo s2=$$ PPID=$PPID
echo "Parent command: $(ps -o cmd= -q $PPID)"

अब, चलो इसे चलाते हैं:

$ bash s1.sh
s1=17955
s2=17956 PPID=17955
Parent command: bash s1.sh

जैसा कि आप दूसरी स्क्रिप्ट देख सकते हैं, वास्तव में, इसके माता-पिता के पीआईडी ​​को जानते हैं। का उपयोग करते हुए ps, कि पीआईडी ​​माता-पिता को आह्वान करने के लिए उपयोग की जाने वाली कमांड लाइन को प्रकट करती है।

PPID की अधिक गहराई से चर्चा के लिए, स्टीफन चेज़लस का उत्तर देखें


धन्यवाद। अपने उदाहरण स्क्रिप्ट मैं चल रहा है s1, s2और PPIDके बाद कई पंक्तियों में मानों लेकिन फिर, ERROR: Unsupported SysV option.के लिए रिक्त मान - और अतिरिक्त स्पष्टीकरण और साथ कई लाइनोंParent command
मायलॉस Đakonović

जॉन आपके प्लेटफॉर्म पर उपलब्ध नहीं है (या अलग तरीके से प्रदान की गई है) कुछ ps सुविधा का उपयोग करके, अपने ps (1) मैनुअल पेज की जाँच करें।
Jasen

@ माइलशियो I ने पैकेज psसे procps-ngसंस्करण 3.3.12 का उपयोग करके परीक्षण किया । जैसा कि जैसन ने सुझाव दिया था, आप एक अलग संस्करण का उपयोग करने की संभावना रखते हैं जिसे माता-पिता की कमांड लाइन को प्रिंट करने के लिए एक अलग सिंटैक्स की आवश्यकता हो सकती है। कोशिश करो ps -f | grep $PPID
John1024
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.