यदि रीडायरेक्शन विफल होगा, तो बैश प्रोग्राम निष्पादित नहीं किया गया


9

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

उदाहरण के लिए, यह प्रोग्राम "a" फाइल को खोलता है और "a" फाइल करने के लिए 50 बाइट्स लिखता है। हालाँकि, इस आदेश को अपर्याप्त अनुमतियों (~ रूट / लॉग) वाली फ़ाइल पर पुनर्निर्देशन के साथ चलाने से "a" के फ़ाइल आकार में कोई परिवर्तन नहीं होता है।

$ ./write_file.py >> ~root/log
-bash: /var/root/log: Permission denied
cdal at Mac in ~/experimental/unix_write
$ ls -lt
total 16
-rw-rw-r--  1 cdal  staff  0 Apr 27 08:54 a <-- SHOULD BE 50 BYTES

किसी को लगता है कि कार्यक्रम चलेगा, किसी भी आउटपुट को कैप्चर करेगा (लेकिन फाइल "a" में भी लिखें), और फिर ~ रूट / लॉग में किसी भी आउटपुट को लिखने में विफल रहें। इसके बजाय कार्यक्रम कभी नहीं चलाया जाता है।

यह क्यों होता है, और यह कैसे "चेक" के क्रम का चयन करता है यह एक कार्यक्रम को निष्पादित करने से पहले करता है? क्या अन्य जाँच भी की जाती हैं?

पीएस मैं यह निर्धारित करने की कोशिश कर रहा हूं कि क्या क्रोन के तहत चलने वाला एक कार्यक्रम वास्तव में "अनुमति से वंचित" फ़ाइल पर पुनर्निर्देशित होने पर चला गया था।


सब कुछ अच्छा काम करने के क्रम में है (यानी आपके .py फ़ाइल की अनुमतियाँ और अनुमतियाँ) आपका प्रोग्राम ठीक निष्पादित करता है। आपकी समस्याएँ अनुप्रेषित से आती हैं। आपको फ़ाइलिन / रूट डायरेक्टरी लिखने की अनुमति नहीं है। और आपने अपने काम stdoutको बिल्कुल वैसा ही कर दिया है। इसलिए, आप कोई भी आउटपुट नहीं देखेंगे, भले ही आपका प्रोग्राम चले।
मेलबर्सलान

2
मेल, यह सच नहीं है, कार्यक्रम वास्तव में कभी नहीं चला। नीचे उत्तर देखें।
चार्ली दलसस

आप: " write_file.pyप्रोग्राम को चलाएं और इसके आउटपुट को ~root/logbash में भेजें :" क्षमा करें, लेकिन आपको उस फ़ाइल को लिखने की अनुमति नहीं है! "शेल बिल्कुल वही कर रहा है जो उसे करना चाहिए। यदि वह ऐसा नहीं कर सकता जो आपने उससे पूछा था। करते हैं, यह आपको तुरंत सूचित करता है कि कोई समस्या क्यों है, जिससे आपको यह तय करने का अवसर मिलता है कि इसके साथ कैसे व्यवहार किया जाए। यदि यह महत्वपूर्ण था कि आपने इसे बचाने के लिए एक स्थान निर्दिष्ट किया हो, तो यह ASS | U | ME के ​​लिए गलत होगा। stdout को बचाए बिना इसे चलाना ठीक था।
मोंटी हार्डर

जवाबों:


18

यह वास्तव में चेक का आदेश देने का सवाल नहीं है, बस वह क्रम जिसमें शेल चीजों को सेट करता है। आदेश चलने से पहले पुनर्निर्देशन की स्थापना की जाती है; इसलिए आपके उदाहरण में, शेल ~root/logकुछ भी शामिल करने की कोशिश करने से पहले अपील करने के लिए खोलने की कोशिश करता है ./write_file.py। चूंकि लॉग फ़ाइल को खोला नहीं जा सकता है, पुनर्निर्देशन विफल हो जाता है और शेल उस बिंदु पर कमांड लाइन को संसाधित करना बंद कर देता है।

इसे प्रदर्शित करने का एक तरीका गैर-निष्पादन योग्य फ़ाइल लेना और इसे चलाने का प्रयास करना है:

$ touch demo
$ ./demo
zsh: permission denied: ./demo
$ ./demo > ~root/log
zsh: permission denied: /root/log

इससे पता चलता है कि शेल ./demoतब भी नहीं दिखता है जब पुनर्निर्देशन सेट नहीं किया जा सकता है।


वाह, यह इतना आसान है? मुझे महसूस नहीं हुआ कि पुनर्निर्देशन पहले किया गया था। इस उत्तर के लिए और अन्य महान उत्तरों के लिए भी धन्यवाद।
चार्ली दलसस

6
यदि वे पहले नहीं किए गए थे, तो आउटपुट को कहां लिखा जाएगा?
चार्ल्स डफी

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

11

से बैश आदमी पेज, खंड REDIRECTION (मेरे द्वारा जोर):

एक कमांड निष्पादित होने से पहले , इसके इनपुट और आउटपुट को शेल द्वारा व्याख्या किए गए विशेष नोटेशन का उपयोग करके पुनर्निर्देशित किया जा सकता है।

...

फ़ाइल खोलने या बनाने में विफलता पुनर्निर्देशन को विफल करने का कारण बनती है।

इसलिए शेल लक्ष्य फ़ाइल को खोलने की कोशिश करता है stdout, जो विफल हो जाता है, और कमांड को निष्पादित नहीं किया जाता है।


बहुत बहुत धन्यवाद। मेरी इच्छा है कि मैन पेज ने थोड़ा स्पष्ट किया "... यदि आउटपुट पुनर्निर्देशित नहीं किया जा सकता है, तो प्रोग्राम निष्पादित नहीं किया जाएगा"।
चार्ली दलसस

अपडेट किया गया; यह बल्कि नीचे कुछ पैराग्राफ छिपा है।
मर्फी

वास्तव में, यह बहुत स्पष्ट है। "फ़ाइल खोलने या बनाने में विफलता के कारण पुनर्निर्देशन विफल हो जाता है।" वो रहा। एक बार फिर धन्यवाद।
चार्ली दलसस

3

यह देखने योग्य है कि कार्यक्रम शुरू करने से पहले शेल को पुनर्निर्देशन स्थापित करना चाहिए

अपने उदाहरण पर विचार करें:

./write_file.py >> ~root/log

शेल में क्या होता है:

  1. हम (खोल) fork(); बाल प्रक्रिया अपने माता-पिता (खोल) से खुली फाइल के विवरणकों को विरासत में देती है।
  2. बच्चे की प्रक्रिया में, हम fopen()() का विस्तार "~ रूट / लॉग", और dup2()यह 1 एफडी (और close()अस्थायी एफडी)। यदि fopen()विफल रहता है, exit()तो माता-पिता को त्रुटि रिपोर्ट करने के लिए कॉल करें ।
  3. अभी भी बच्चे में, हम exec()"./write_file.py"। यह प्रक्रिया अब हमारे किसी भी कोड को नहीं चला रही है (जब तक कि हम निष्पादित करने में विफल नहीं होते हैं, उस स्थिति में हम exit()माता-पिता को त्रुटि की सूचना देते हैं )।
  4. माता-पिता wait()बच्चे को समाप्त करने के लिए, और इसके निकास कोड ( $?कम से कम, इसे कॉपी करके ) को संभालेंगे ।

इसलिए पुनर्निर्देशन बच्चे के बीच में होना चाहिए : fork()और exec()ऐसा पहले नहीं हो सकता fork()क्योंकि इसमें शेल के स्टडआउट को नहीं बदलना चाहिए, और ऐसा exec()इसलिए नहीं हो सकता क्योंकि फ़ाइल नाम और शेल के निष्पादन योग्य कोड को अब पायथन प्रोग्राम द्वारा बदल दिया गया है । माता-पिता के पास बच्चे के फाइल डिस्क्रिप्टर तक कोई पहुंच नहीं है (और अगर ऐसा किया भी था, तो वह बीच exec()- बीच में पहले रीडायरेक्ट करने की गारंटी नहीं दे सकता था )।


0

मुझे आपको सूचित करने के लिए खेद है कि यह काफी विपरीत है। खोल को पहले I / O खोलने की आवश्यकता है और फिर कार्यक्रम पर नियंत्रण पास करना है।

tee इस मामले में मददगार साबित हो सकता है: ./write_file.py | tee -a ~root/log > /dev/null


केवल असफल होने के बाद अजगर स्क्रिप्ट SIGPIPE पर नहीं मरेंगे?
केविन

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