शेल स्क्रिप्ट को निष्पादित करने के विभिन्न तरीके


44

स्क्रिप्ट निष्पादित करने के कई तरीके हैं, जिन्हें मैं जानता हूं:

/path/to/script # using the path (absolute or relative)
. script        # using the . (dot)
source script   # using the `source` command

क्या ये ज्यादा हैं? उनके बीच क्या अंतर हैं? क्या ऐसी परिस्थितियाँ हैं जो मुझे एक का उपयोग करना चाहिए और दूसरे का नहीं?


आपके प्रश्न और उत्तर के लिए धन्यवाद, विशेष रूप से शॉन के नीचे। मैं कुछ ऐसी चीजें जोड़ना चाहूंगा जो मेरे लिए बहुत स्पष्ट नहीं थीं जब तक कि मैं कुछ परीक्षण नहीं करता। ऊपर के दूसरे तरीके में "/" को शामिल करने से कमांड को मोड 1 से ऊपर ले जाया जाएगा। यही है, जबकि "./myscript.sh" मोड 1 का अनुसरण करता है, "myscript.sh" मोड 2 से चिपक जाता है। आपने "पथ (पूर्ण या रिश्तेदार) का उपयोग करते हुए" का उल्लेख किया था, लेकिन बस इसे स्पष्ट करना चाहते थे।
अरुण

जवाबों:


32

एक और तरीका है दुभाषिया को बुलाना और उसके लिए स्क्रिप्ट को रास्ता देना:

/bin/sh /path/to/script

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

स्क्रिप्ट चलाने के अन्य तरीके इसे अपने स्वयं के उप-भाग में चलाएंगे। स्क्रिप्ट में चर अभी भी जीवित नहीं हैं जब यह किया जाता है। यदि स्क्रिप्ट ने निर्देशिकाओं को बदल दिया है, तो यह कॉलिंग के वातावरण को प्रभावित नहीं करता है।

/ path / to / script और / bin / sh स्क्रिप्ट थोड़ी अलग हैं। आमतौर पर, एक स्क्रिप्ट में शुरुआत में "शेबंग" होता है जो इस तरह दिखता है:

#! /bin/bash

यह स्क्रिप्ट दुभाषिया का रास्ता है। यदि यह निष्पादित करते समय आप की तुलना में एक अलग दुभाषिया निर्दिष्ट करता है, तो यह अलग तरह से व्यवहार कर सकता है (या बिल्कुल भी काम नहीं कर सकता है)।

उदाहरण के लिए, पर्ल स्क्रिप्ट और रूबी स्क्रिप्ट क्रमशः (क्रमशः) से शुरू होती हैं:

#! /bin/perl

तथा

#! /bin/ruby

यदि आप दौड़कर उनमें से किसी एक स्क्रिप्ट को निष्पादित करते हैं /bin/sh script, तो वे बिल्कुल भी काम नहीं करेंगे।

उबंटू वास्तव में बैश शेल का उपयोग नहीं करता है, लेकिन एक बहुत ही समान जिसे डैश कहा जाता है। बाॅस की आवश्यकता होने पर लिपियों को गलत तरीके से काम करने से बुलाया जा सकता है /bin/sh scriptक्योंकि आपको सिर्फ डैश दुभाषिया का उपयोग करके बश लिपि कहा जाता है।

स्क्रिप्ट को सीधे कॉल करने और इंटरप्रेटर के लिए स्क्रिप्ट पथ पास करने के बीच एक और छोटा अंतर यह है कि स्क्रिप्ट को सीधे चलाने के लिए निष्पादन योग्य चिह्नित किया जाना चाहिए, लेकिन दुभाषिया के लिए मार्ग को पारित करके इसे चलाने के लिए नहीं।

एक और मामूली भिन्नता: आप किसी भी तरीके से किसी स्क्रिप्ट को निकालने के लिए उपसर्ग कर सकते हैं, इसलिए, आपके पास हो सकता है

eval sh script
eval script
eval . script

और इसी तरह। यह वास्तव में कुछ भी नहीं बदलता है, लेकिन मुझे लगा कि मैं इसे पूरी तरह से शामिल करूंगा।


6
"उबंटू वास्तव में बैश शेल का उपयोग नहीं करता है" कहना गलत और तकनीकी रूप से गलत है। उबंटू बैश शेल का उपयोग करता है , बिंदु यह है कि इसके shअनुरूप है dash, लेकिन नहीं bash
फहीम मीठा

@ शॉन फ़र्स्ट पैरा में आपने लिखा है "यह स्क्रिप्ट को अंदर ले जाता है (जैसे कि आपने कॉपी की है और स्क्रिप्ट को वहीं चिपका दिया है)। इसका मतलब है कि स्क्रिप्ट में कोई भी फ़ंक्शन और गैर-स्थानीय चर बने हुए हैं।" यहाँ दूसरी पंक्ति से आपका क्या मतलब है? क्या आप समझा सकते हैं।
गीक

@ गीक जब आप एक स्क्रिप्ट को एक बच्चे की प्रक्रिया (सामान्य तरीके) के रूप में निष्पादित करते हैं, तो कोई भी चर और फ़ंक्शन जो इसे परिभाषित करता है (यह पर्यावरण है) प्रक्रिया समाप्त होने पर चले जाते हैं। यदि आप स्क्रिप्ट का स्रोत बनाते हैं, तो उन चर और कार्यों को वर्तमान परिवेश में बनाया जाता है; जब स्क्रिप्ट खत्म हो जाती है, तो पर्यावरण में बदलाव बना रहता है।
शॉन जे। गोफ

@ ShawnJ.Goff स्पष्टीकरण के लिए धन्यवाद। +1।
गीकू

प्लॉट-ट्विस्ट: बॉर्न शेल (श) केवल डॉट को स्वीकार करता है - स्रोत नहीं क्योंकि यह बैश-बिलिन है। pubs.opengroup.org/onlinepubs/9699919799/utilities/… तो मैं कहूंगा कि सबसे पोर्टेबल तरीका एक डॉट है।
देज़ज़ा

9

अधिकांश लोग स्क्रिप्ट में निम्न डीबगिंग फ़्लैग जोड़कर शेल स्क्रिप्ट को डीबग करते हैं:

set -x     # Print command traces before executing command.
set -v     # Prints shell input lines as they are read.
set -xv    # Or do both

लेकिन इसका मतलब है कि आपको एक संपादक के साथ फ़ाइल खोलने की आवश्यकता है (यह मानते हुए कि आपके पास फ़ाइल को संपादित करने की अनुमति है), एक पंक्ति जोड़कर set -x, फ़ाइल को सहेजें, फिर फ़ाइल निष्पादित करें। फिर जब आपको किया जाता है तो आपको उसी चरणों का पालन करने और set -xइत्यादि को हटाने की आवश्यकता होती है , आदि। यह थकाऊ हो सकता है।

वह सब करने के बजाय, आप कमांडिंग पर डिबगिंग झंडे सेट कर सकते हैं:

$ bash -x ~/bin/ducks
+ du -cks -x dir1 dir2 dir3 file1 file2 file3
+ sort -n
+ tail .ducks
123 etc
424 bin
796 total



$ sh -xv ~/bin/ducks  
#!/usr/bin/env bash

# Find the disk hog
# Borrowed from http://oreilly.com/pub/h/15
...
...

2
एक संबंधित टिप: मैंने emulate sh 2>/dev/nullअपने शेल स्क्रिप्ट के शीर्ष पर रखने की आदत डाल ली है । जब zsh के साथ चलाया जाता है, तो यह इसे POSIX संगत मोड में डालता है। जब अन्य गोले के साथ चलाया जाता है, तो लाइन का कोई प्रभाव नहीं होता है। तब मैं स्क्रिप्ट चला सकता हूं zsh -x /path/to/script। मुझे यहाँ zsh पसंद है क्योंकि यह bash या ksh से बेहतर निशान प्रदान करता है।
गिल्स एसओ- बुराई को रोकें '

7

शॉन जे। गोफ ने बहुत अच्छे अंक बनाए, लेकिन पूरी कहानी को शामिल नहीं किया:

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

बहुत सारी सिस्टम स्क्रिप्ट (जैसे init.d, in / etc वगैरह) में एक शेबंग है #!/bin/sh, लेकिन /bin/shवास्तव में एक अन्य शेल के लिए एक प्रतीकात्मक लिंक है - पूर्व समय में /bin/bash, आजकल /bin/dash। लेकिन जब उनमें से एक के रूप में आमंत्रित किया जाता है /bin/sh, तो वे अलग तरह से व्यवहार करते हैं, अर्थात वे पोसिक्स-संगतता-मोड से चिपके रहते हैं।

वे ऐसा कैसे करते हैं? खैर, वे निरीक्षण करते हैं कि उन्हें कैसे लागू किया गया था।

क्या कोई शेलस्क्रिप्ट स्वयं परीक्षण कर सकता है कि यह कैसे लागू किया गया था, और उसके आधार पर अलग-अलग चीजें करते हैं? हाँ यह कर सकते हैं। तो जिस तरह से आप इसे लागू करते हैं वह हमेशा अलग परिणाम दे सकता है, लेकिन निश्चित रूप से यह शायद ही कभी आपको परेशान करने के लिए किया जाता है। :)

अंगूठे के एक नियम के रूप में: यदि आप बैश की तरह एक विशिष्ट शेल सीख रहे हैं, और एक बैश ट्यूटोरियल से कमांड लिखते हैं, #!/bin/bashतो हेडलाइन में डाल दिया जाता है, न #!/bin/shकि जहां अन्यथा नोट किया गया है। आपकी आज्ञा विफल हो सकती है। और यदि आपने स्वयं कोई स्क्रिप्ट नहीं लिखी है, तो एक शेल ( , ) का अनुमान लगाने के बजाय इसे सीधे ( ./foo.sh, bar/foo.sh) लागू करें । शेबंग को सही खोल देना चाहिए।sh foo.shsh bar/foo.sh

और यहाँ दो अन्य प्रकार के आह्वान हैं:

cat foo.sh | dash
dash < foo.sh

5

.और sourceइसके बराबर हैं कि वे एक सबप्रोसेस नहीं बनाते हैं लेकिन वर्तमान शेल में कमांड निष्पादित करते हैं। यह महत्वपूर्ण है जब स्क्रिप्ट वातावरण चर निर्धारित करती है या वर्तमान कार्य निर्देशिका को बदलती है।

पथ का उपयोग करना या इसे देना /bin/shएक नई प्रक्रिया बनाता है जिसमें कमांड निष्पादित होते हैं।


2
sh script
bash script

ज्यादा होने पर मैं विचार कर रहा हूं ...

.और sourceसमान हैं। निष्पादन के बाद पर्यावरण के किसी भी परिवर्तन को scriptरखा जाएगा। आमतौर पर, इसका उपयोग बैश लाइब्रेरी के स्रोत के लिए किया जाता है, इसलिए लाइब्रेरी को कई अलग-अलग लिपियों में फिर से उपयोग किया जा सकता है।

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


2
.केवल श / बाश और संबंधित गोले में काम करता है। sourcecsh और संबंधित गोले में भी काम करता है।
कीथ

1

क्या " उपयोगकर्तालैंड निष्पादन " को एक अलग तरीके से गिना जाता है? उपयोगकर्तालैंड लोड कोड को निष्पादित करता है और इसे निष्पादित () सिस्टम कॉल के उपयोग के बिना निष्पादित करने के लिए मिलता है।


1
. ./filename
# ( dot space dot slash filename )

जब स्क्रिप्ट पथ में नहीं है तो वर्तमान शेल में स्क्रिप्ट चलाता है।


1

। और स्रोत zsh में कम से कम थोड़ा अलग है (यही वह है जो मैं उपयोग करता हूं) क्योंकि

source file

काम करता है, जबकि

. file

जरूरत नहीं है

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