एक बैश स्क्रिप्ट सोर्स करना - एक्ज़िट के बजाय एरर पर लौटें?


17

मैं टर्मिनल में बैश स्क्रिप्ट सोर्स कर रहा हूं , इसलिए त्रुटि के साथ बाहर निकल रहा हूं

set -o errexit

मेरे टर्मिनल को मारता है, जो पूरी तरह से बंद है, क्योंकि मुझे टर्मिनल बंद करना है, एक और खोलना है, और कुछ चर रीसेट करना है।

अब तक, का उपयोग कर

command || return

लाइनों, स्क्रिप्ट में, मैं जो चाहता हूं वही कर रहा हूं

set -o errexit

करने के लिए ... लेकिन मैं इसे पूरी स्क्रिप्ट के लिए करना चाहता हूं; सिर्फ एक लाइन / कमांड नहीं

मेरे पास एक साइट स्थापित करने के लिए आदेशों से भरा एक फ़ाइल है, और मैं इसके बजाय कमांड नहीं करूँगा || वापसी

फ़ाइल में हर एक पंक्ति के लिए

क्या दूसरा सेट विकल्प है, या कुछ और है जो टर्मिनल से बाहर निकलने के बजाय सिर्फ "वापसी" करेगा?

- स्पष्टता के लिए , मैं स्क्रिप्ट को मारना चाहूंगा, और टर्मिनल को उसी स्थिति में छोड़ दूंगा, जो टर्मिनल में चल रही सेवा को मारने के लिए ctrl + C दबाएगा। command || returnक्या वो। लेकिन मैं || returnफ़ाइल में हर पंक्ति से निपटना नहीं चाहता । तो मैं कुछ इसी तरह की तलाश कर रहा हूं set -o errexit, जिससे टर्मिनल बंद न हो

--- नोट: इसमें दो पंक्तियों के साथ एक डंब स्क्रिप्ट बनाना (सुपर.श):

create_path=~/Desktop/site_builder/create.sh
source $create_path blah

और set -o errexitcreate.sh के शीर्ष पर रखते हुए,

ठीक वैसा ही काम करता है जैसा मैं उम्मीद करता हूं। हालाँकि, यह वास्तव में बेवकूफ है कि इसमें दो पंक्तियों के साथ एक फ़ाइल बनाई जाए, बस एक और बैश स्क्रिप्ट को कॉल करने के लिए, बजाय इसे टर्मिनल से कॉल करने के। Ugghhh

यहाँ कुछ उदाहरण हैं:

सुपर में

#!/bin/bash

create_path=~/Desktop/site_builder/create.sh
source $create_path blah

create.sh में

#!/bin/bash
set -o errexit
#line below this is a line that fails and will cause the script to stop and return to the terminal as expected 
sed "s/@@SITE_NAME@@/$dirname" 
~/Desktop/site_builder/template_files/base.html > ~/Desktop/$dirname/templates/base.html # a line with a stupid error

टर्मिनल में:

 $ bash super.sh

उम्मीद के मुताबिक उत्पादन:

my-mac$

यह काम। क्या कष्टप्रद समाधान है।

मैं , आदर्श रूप से निष्पादित करना चाहता हूं कि टर्मिनल से बेवकूफ सुपर.श फ़ाइल में क्या है, सुपर.श फ़ाइल नहीं: डी, ​​मेरे बिना टर्मिनल बंद होने के बिना। यह वही है जो मैं करने की कोशिश कर रहा हूं:

टर्मिनल कमांड:

my-mac$ source $create_path blah

create.sh में मेरे पास अभी भी है set -o errexit

यहाँ टर्मिनल पर आउटपुट है

    sed: 1: "s/@@SITE_NAME@@/blah": unterminated substitute in regular expression
Saving session...
...copying shared history...
...saving history...truncating history files...
...completed.

[Process completed]

और फिर टर्मिनल जम गया है। Ctrl + C काम नहीं करता है, न ही Ctrl + D

अगर इसके बजाय set -o errexit, अगर मैं command || returncreate.sh फ़ाइल में हर जगह केवल स्टेटमेंट्स का उपयोग करता हूं, तो मुझे सीधे वही मिलता है जो मैं चाहता हूं, जबकि सीधे टर्मिनल पर supser.sh में लाइनों को निष्पादित करता है (टर्मिनल से सुपर.श को कॉल करने के बजाय)। लेकिन यह एक व्यावहारिक समाधान भी नहीं है।

नोट: मुझे @terdon का उत्तर सिर्फ एक बच्चे के खोल को पैदा करने के बारे में पसंद आया इसलिए मैंने टर्मिनल के बजाय स्क्रिप्ट के माध्यम से एक उप शेल को समाप्त कर दिया, जैसा कि उसने अपने उत्तर में ब्रेसिज़ का उपयोग करके दिखाया ( ), पूरी स्क्रिप्ट के आसपास .. उसका उत्तर काम भी करता है।


क्या आप इसे स्क्रिप्ट या मैन्युअल रूप से कर रहे हैं?
terdon

मैं फाइल को टर्मिनल में स्रोत के साथ बुला रहा हूं। जैसे: source $file_path argumentस्क्रिप्ट को उसी शेल में निष्पादित किया जा रहा है जिसे मैंने इसे कॉल किया था (क्या sourceकरता है, मुझे बताया गया है ... और इस तरह काम करता है) command || returnस्टेटमेंट फाइल में हैं जिसे मैं टर्मिनल में निष्पादित कर रहा हूं

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

मैंने मूल पोस्ट में एक नोट जोड़ा है जो इसके साथ मदद कर सकता है। लेकिन जैसा कि आपने सुझाव दिया है, मैं भी करूंगा।

जवाबों:


5

बस फ़ाइल को किसी असफल श्रेणी के साथ स्रोत:

source the-source-file || true

... तो समग्र आदेश विफल हो जाएगा, भले ही sourceकरता है।


वास्तव में, मुझे लगा कि यह वही है जो मैं चाहता था, लेकिन पता चला कि मेरा टर्मिनल अभी धीमा चल रहा था ... मैं वास्तव में त्रुटि पर टर्मिनल पर लौटना चाहता हूं, (इसका मतलब है कि यह पूरी स्क्रिप्ट को पटरियों में बंद कर देता है) .. और जो भी कारण हो। source file || true ऐसा नहीं करता है, न ही source file || return जब मैं इसे टर्मिनल में टाइप करता हूं ...

फ़ाइल को सोर्स करना आपको शेल प्रॉम्प्ट में नहीं लौटाता है ??
जेफ स्कालर

यह मेरे टर्मिनल में है: Jills-MBP:~ jillr$ source ~/Desktop/site_builder/create.sh blah || trueयह बस स्क्रिप्ट के अगले भाग को विफल करता है, इसलिए यह सच होने के बजाय वापस आ जाता है। केवल एक चीज जिसने काम किया है command || returnवह सभी कमांड के लिए वास्तविक फ़ाइल में स्टेटमेंट्स है, जो मूर्खतापूर्ण है। मुझे नहीं पता कि अगर यह सब किसी फ़ंक्शन में है तो function || returnफ़ाइल के अंत में कॉल करने से कोई भी अच्छा काम करेगा।

ठीक है, यदि आप स्पष्ट रूप || returnसे एक कमांड पर डालते हैं जो विफल रहता है, हाँ, यह वापस आ जाएगा। मुझे लगा कि हम आपके मुख्य / माता-पिता को बाहर निकलने से रोकने की कोशिश कर रहे हैं?
जेफ स्कालर

हां, मैं टर्मिनल को वास्तव में बाहर रखना चाहता हूं। क्योंकि मैं टर्मिनल से बाहर नहीं निकलना चाहता। मैं स्क्रिप्ट से बाहर निकलना चाहता हूं। स्क्रिप्ट में अलग-अलग आदेशों पर लौटें स्क्रिप्ट से बाहर निकलता है और मेरे टर्मिनल को उसी स्थिति में छोड़ देता है जैसे कि एक प्रक्रिया को मारने के लिए Ctrl + C दबाता है, जैसे कि सर्वर को टर्मिनल के रूप में चलाना। मैं कमांड लिखने से बचना चाहता हूँ || फ़ाइल में हर पंक्ति के लिए वापसी: D

3

यह केवल एक चीज है जो मुझे पूरा करने के लिए काम करती है (एक आभासी वातावरण बनाना, फिर इसे सक्रिय करना, फिर एक स्क्रिप्ट से आवश्यकताओं को स्थापित करना):

स्क्रिप्ट से एक सबशेल / चाइल्ड शेल स्पॉन करें, जैसे:

stupid_file.sh

(
set -o errexit
#bunch of commands
#one line fails
)

बेवकूफ_फाइल का उपयोग करके चलाएं:

source stupid_file.sh <file arguments here> || true

समाप्त।

** धनुष लेता है **

(श्रेय जेफ और टेर्डन को जाता है)


1
यह वास्तव में सोर्सिंग के बजाय स्क्रिप्ट को निष्पादित करने से अलग नहीं है।
Chepner

@ शेपनर हम्म। ठंडा। मुझे बस कॉल करने का प्रयास करना होगा bash $create_path blahऔर देखना होगा कि क्या यह अभी भी बाहर निकलता है, और उसी तरह निष्पादित होता है, और अभी भी मेरे वर्चुअल वातावरण में सामान को सही तरीके से स्थापित करता है। अब समय से बाहर

मैं आपको समय बचाऊंगा: यह (यदि "सामानों को स्थापित करने से" का अर्थ है कि आप अपने वर्तमान शेल में पर्यावरण चर सेट करते हैं), और न ही करेंगे (...), क्योंकि कोष्ठक में सभी असाइनमेंट केवल उसी उपधारा को प्रभावित करते हैं। foo=3; (foo=5); echo "$foo"उत्पादन 3 होगा, 5 नहीं
chepner

@chepner बिल्कुल नहीं। मैं source fileटर्मिनल से फोन नहीं कर सकता और उसी परिणाम की उम्मीद कर सकता हूं । क्योंकि वह कभी काम नहीं किया। केवल वही समय मिलता है जब मैं एक उप शेल स्पष्ट रूप से बनाता हूं, चाहे टर्मिनल के माध्यम से, या स्क्रिप्ट से। हालांकि मैं स्क्रिप्ट को निष्पादित करने के bashबजाय उपयोग कर सकता हूं source, और समान परिणाम प्राप्त कर सकता हूं, लेकिन केवल तभी जब मैं अपनी स्क्रिप्ट को एक उप शेल में स्पष्ट रूप से निष्पादित करता हूं

@ सामान को स्थापित करके, मेरा वास्तव में मतलब है कि एक आभासी वातावरण बनाएं, उस आभासी वातावरण को सक्रिय करें, और फिर pip install -r $apath/requirements.txtउस सक्रिय वातावरण में निष्पादित करें । यही कारण है कि मैंने स्क्रिप्ट को कॉल करने के लिए पहले स्थान पर स्रोत का उपयोग किया

1

एक साधारण वर्कअराउंड के रूप में, आप अपने वर्तमान शेल और स्रोत में एक शेल चला सकते हैं। कुछ इस तरह:

  1. एक नया टर्मिनल खोलें और अपनी इच्छानुसार सब कुछ सेट करें। आपने कुछ पर्यावरण चर और पसंद का उल्लेख किया है। उन्हें यहाँ सेट करें।

  2. उस टर्मिनल में, एक नया शेल शुरू करें। उदाहरण के लिए, bash

  3. अपना काम करो। अपनी स्क्रिप्ट का स्रोत। यदि यह बाहर निकलता है, तो आप बस पहले शेल में फेंक दिए जाते हैं और सब कुछ अभी भी सेट है। बस bashफिर से चलाएं और आप व्यवसाय में वापस आ गए हैं।

वर्णन करने के लिए, मैंने यह स्क्रिप्ट बनाई है जो विफल हो जाएगी यदि आप इसे स्रोत करने की कोशिश करते हैं:

$ cat /home/terdon/scripts/bar.sh
set -o errexit
var='bar

आइए देखें कि क्या होता है यदि मैं एक नेस्टेड शेल सत्र शुरू करता हूं और फिर इसे स्रोत करता हूं (ध्यान दें कि मैं sourceकमांड के लिए पोर्टेबल नाम का उपयोग कर रहा हूं .; sourceएक बशीवाद है):

parent-shell $ bash      ## start a new shell
child-shell $ . ~/scripts/bar.sh
bash: /home/terdon/scripts/bar.sh: line 2: unexpected EOF while looking for matching `''
parent-shell $ 

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


मैं यह बहुत जल्दी कोशिश करने जा रहा हूँ

इसका अभीष्ट प्रभाव है ... नकारात्मक पक्ष यह है कि जो चर मैं माता-पिता के खोल के लिए बनाता हूं, वे बच्चे के खोल में सुलभ नहीं होते हैं, जिनमें से एक चर मैं बच्चे के खोल में निष्पादन के लिए आवश्यक होता है। क्या मैं जिस फ़ाइल को निष्पादित कर रहा हूं, उससे एक सब-टाइम स्पॉन करने का एक तरीका है? इस तरह, मैं अभी भी मूल शेल में स्क्रिप्ट को कॉल कर सकता हूं, और अभी भी उन चर तक पहुंच सकता हूं जिनकी मुझे आवश्यकता है? मैं create_path=~/Desktop/site_builder/create.sh मूल रूप से मूल शैल में स्थापित कर रहा हूं क्योंकि मैं ऐसा अक्सर करता हूं। और मुझे स्क्रिप्ट निष्पादित करने के लिए स्रोत $ create_path [तर्क] को कॉल करने की आवश्यकता है।

1
@JillRussek अगर चर बच्चे के गोले को पारित नहीं किया जा रहा है, तो आप exportउन्हें नहीं कर सकते। लेकिन आप जो वर्णन करते हैं वह वास्तव में बहुत कम समझ में आता है। यह एक XY समस्या की तरह अधिक से अधिक लग रहा है । आप एक नया प्रश्न बताना चाहते हैं कि आपका अंतिम उद्देश्य क्या है। मुझे यकीन है कि हम आपको एक बेहतर समाधान दे सकते हैं कि यह सब अजीब सोर्सिंग है।
terdon

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

लेकिन आप सही हैं, मैं चर का निर्यात नहीं कर रहा था, क्योंकि मुझे नहीं पता था कि मुझे इसकी आवश्यकता है: डी। (मैंने पहले एक बच्चे का खोल नहीं देखा है)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.