एक शेल स्क्रिप्ट को दूसरे शेल स्क्रिप्ट से कैसे कॉल करें?


737

मेरे पास दो शेल स्क्रिप्ट हैं, a.shऔर b.sh

मैं b.shशेल स्क्रिप्ट के भीतर से कैसे कॉल कर सकता हूं a.sh?


8
क्या आप कुछ बारीकियाँ दे सकते हैं: कौन सा OS और कौन सा शेल (s) या आप सिद्धांत रूप में उस समस्या के बारे में बात कर रहे हैं ?? उदाहरण कोड उपयोगी होगा।
jsalonen 7

14
यह वास्तव में एक विशिष्ट प्रश्न नहीं है और न ही इस मुद्दे को हल करने के लिए पूर्व प्रयास प्रदर्शित करता है।
क्रिश

1
मेरे पास एक मुद्दा यह था कि b.shनिष्पादन योग्य अनुमति नहीं थी। जांच करना अच्छी बात हो सकती है।
सेठ १०

संलग्न ./करने से पहले स्क्रिप्ट नाम, उदाहरण के लिए, बजाय: b.sh, उपयोग:./b.sh
बेनी

1
अगर किसी को भी No such file or directoryत्रुटि हो रही है stackoverflow.com/a/2920431/1356559
अमृत ​​लॉट

जवाबों:


957

कुछ अलग तरीके हैं जिनसे आप यह कर सकते हैं:

  1. अन्य स्क्रिप्ट को निष्पादन योग्य बनाएं, #!/bin/bashशीर्ष पर लाइन जोड़ें , और पथ जहां फ़ाइल $ PATH पर्यावरण चर है। तब आप इसे सामान्य आदेश कह सकते हैं;

  2. या इसे sourceकमांड (उपनाम .) के साथ इस तरह से कॉल करें source /path/to/script:;

  3. या bashइसे निष्पादित करने के लिए कमांड का उपयोग करें /bin/bash /path/to/script:;

पहले और तीसरे तरीके स्क्रिप्ट को एक और प्रक्रिया के रूप में निष्पादित करते हैं, इसलिए दूसरी स्क्रिप्ट में चर और फ़ंक्शन सुलभ नहीं होंगे।
दूसरी विधि पहले स्क्रिप्ट की प्रक्रिया में स्क्रिप्ट को निष्पादित करती है, और अन्य स्क्रिप्ट से चर और कार्यों में खींचती है ताकि वे कॉलिंग स्क्रिप्ट से उपयोग करने योग्य हों।

दूसरी विधि में, यदि आप exitदूसरी स्क्रिप्ट का उपयोग कर रहे हैं, तो यह पहली स्क्रिप्ट से भी बाहर निकल जाएगी। जो पहले और तीसरे तरीके में नहीं होगा।


30
याद रखें chmod a+x /path/to/fileवरना यह निष्पादन योग्य नहीं होगा। केवल ./script विधि पर लागू होता है।
नाथन लिलिएनथाल

3
यदि उन्हें DOS में बनाया गया है तो यूनिक्स में निष्पादन योग्य फ़ाइलों के प्रारूप / एन्कोडिंग को बदलना याद रखें और फिर यूनिक्स के वातावरण में अपलोड करें -> dos2unix <script नाम>
अभिषेक चटर्जी

3
@cecemel सामान्य रन-इन-बैकग्राउंड सिंटैक्स का उपयोग करके पहला और तीसरा तरीका "async" हो सकता है।
कुछ प्रोग्रामर

16
इसके साथ समस्या sourceयह है कि exitकहा जाता है कि स्क्रिप्ट में एक बयान के रूप में अच्छी तरह से तुम्हारा बाहर निकल जाएगा ...
Ohad Schneider

18
@ user528025 के .लिए एक उपनाम नहीं है source, बल्कि अन्य तरीके से। sourceएक bash एक्सटेंशन है, जबकि .किसी भी POSIX संगत शेल में काम करता है।
स्कोर_उंडर

207

इसकी जांच करें।

#!/bin/bash
echo "This script is about to run another script."
sh ./script.sh
echo "This script has just run another script."

4
यह मानता है कि script.sh उसी निर्देशिका में है, जो भी स्क्रिप्ट चल रही है। यदि आप एक स्क्रिप्ट को कहीं और कॉल करना चाहते हैं, तो आप कहेंगेsh <path to script>/script.sh
मॉर्गन केनियन

32
यह भी दो गोले का उपयोग करता है , bashऔर sh। यहां तक ​​कि जब shवास्तव में bashयह एक ही व्यवहार नहीं करता है। यदि आप उपयोग कर रहे हैं #!/bin/bashतो आप शायद उपयोग करना चाहते हैं bash script.sh(या बस ./script.shउस स्क्रिप्ट के हैशबैंग का उपयोग करना चाहते हैं )।
बजे मार्टिन टूरनोइज

1
जब मैं chmod +x.sh फ़ाइल को सेट करता हूं तब भी अनुमति प्राप्त होने से इनकार किया गया । कोई सुझाव?
इसहाक बुनाई 7

@isaacweathers ने chmod 777
Janac Meena

114

ऐसे कुछ तरीके हैं जिनसे आप यह कर सकते हैं। स्क्रिप्ट निष्पादित करने के लिए टर्मिनल:

#!/bin/bash
SCRIPT_PATH="/path/to/script.sh"

# Here you execute your script
"$SCRIPT_PATH"

# or
. "$SCRIPT_PATH"

# or
source "$SCRIPT_PATH"

# or
bash "$SCRIPT_PATH"

# or
eval '"$SCRIPT_PATH"'

# or
OUTPUT=$("$SCRIPT_PATH")
echo $OUTPUT

# or
OUTPUT=`"$SCRIPT_PATH"`
echo $OUTPUT

# or
("$SCRIPT_PATH")

# or
(exec "$SCRIPT_PATH")

यह सब रिक्त स्थान वाले मार्ग के लिए सही है !!!


41
उनके मतभेद क्या हैं? एक क्यों, दूसरा क्यों?
रॉकेट्सपेजर

। "$ SCRIPT_PATH" को पसंद किया जाता है
हैरी ममफोर्ड-टर्नर

1
मैं सिर्फ इतना जोड़ सकता हूं कि ये सभी समतुल्य नहीं हैं, जैसे sh "$ SCRIPT_PATH" और "$ SCRIPT_PATH" को नहीं चलाएंगे #! / Usr / bin / उम्मीद स्क्रिप्ट, जबकि बस "$ RCRIPT_PATH" नहीं चलेगा।
ताहलोर

58

जवाब जो मैं देख रहा था:

( exec "path/to/script" )

जैसा कि उल्लेख किया गया है, execएक नई प्रक्रिया बनाए बिना शेल को बदल देता है। हालांकि , हम इसे एक उप-संस्करण में रख सकते हैं, जो कि परांठे का उपयोग करके किया जाता है।

संपादित करें: वास्तव ( "path/to/script" )में पर्याप्त है।


11
यह बहुत जटिल लगता है। क्यों नहीं बस इसके साथ बुलाओ /path/to/script? मैं execयहाँ सब की आवश्यकता नहीं देख रहा हूँ ?
मार्टिन टूरनोइज

आपके पास नहीं होने के बाद से सबस्क्रिप्शन की आवश्यकता नहीं है exec
करेल वल्क

6
आप इस स्क्रिप्ट को तर्कों के साथ कैसे निष्पादित करेंगे?
भार्गव

यदि आप अभी भी उप-स्क्रिप्ट की कोशिश $ (स्रोत "पथ / टू / स्क्रिप्ट") के उत्पादन पर कब्जा करना चाहते हैं
cmcginty

@ भार्गव इस लिंक का अनुसरण करें stackoverflow.com/questions/14302389/…
tpbafk

16

निर्भर करता है। संक्षेप में ... यदि आप वर्तमान कंसोल पर लोड चर चाहते हैं और source myshellfile.shअपने कोड पर उपयोग कर सकते हैं । उदाहरण:

!#/bin/bash
set -x
echo "This is an example of run another INTO this session."
source my_lib_of_variables_and_functions.sh
echo "The function internal_function() is defined into my lib."
returned_value=internal_function()
echo $this_is_an_internal_variable

set +x

यदि आप किसी फ़ाइल को निष्पादित करना चाहते हैं और केवल एक चीज जो आपके लिए अंतरालीय है, तो आप यह कर सकते हैं:

!#/bin/bash
set -x
./executing_only.sh
sh i_can_execute_this_way_too.sh
bash or_this_way.sh
set +x

मुझे आशा है कि आपकी मदद करेगा। धन्यवाद।


2
ध्यान दें कि sourceएक बैश-विशिष्ट विशेषता है। मानक बोर्न शेल में केवल .(जैसे . other_script.sh) है।
मार्टिन टूरनोइज

15

आप /bin/shकिसी अन्य स्क्रिप्ट को (अपनी वास्तविक स्क्रिप्ट के माध्यम से) कॉल या निष्पादित करने के लिए उपयोग कर सकते हैं :

 # cat showdate.sh
 #!/bin/bash
 echo "Date is: `date`"

 # cat mainscript.sh
 #!/bin/bash
 echo "You are login as: `whoami`"
 echo "`/bin/sh ./showdate.sh`" # exact path for the script file

उत्पादन होगा:

 # ./mainscript.sh
 You are login as: root
 Date is: Thu Oct 17 02:56:36 EDT 2013

1
निश्चित रूप से यह showdate.sh/ बिन / बाश के बजाय / बिन / श के तहत चलेगा ?
क्रिस वाट

मैंने " /bin/sh ./showdate.sh", " /bin/bash ./showdate.sh", " ./showdate.sh" और फ़ाइल चलाने की कोशिश की है: mainscript.sh और उसी आउटपुट को मिला।
रंजीथकुमार टी

10

बस स्क्रिप्ट को निष्पादित करने के लिए एक टर्मिनल में टाइप किया जाएगा जो कुछ भी एक पंक्ति में जोड़ें!
उदाहरण के लिए:

#!bin/bash
./myscript.sh &

यदि स्क्रिप्ट को निष्पादित किया जा रहा है तो वह उसी डायरेक्टरी में नहीं है, बस स्क्रिप्ट के पूर्ण पथ का उपयोग करें।
उदाहरण: `/ घर / उपयोगकर्ता / स्क्रिप्ट-निर्देशिका / / / myscript.sh और


@Carpetsmoker &बैकग्राउंड टास्क के लिए
आंद्रेई कर्सुटस्की

9

सबसे पहले आपको उस फ़ाइल को शामिल करना होगा जिसे आप कॉल करते हैं:

#!/bin/bash
. includes/included_file.sh

तब आप अपने कार्य को इस तरह कहते हैं:

#!/bin/bash
my_called_function


9

यदि आपके पास उसी निर्देशिका में एक और फ़ाइल है, तो आप या तो कर सकते हैं:

bash another_script.sh

या

source another_script.sh

या

. another_script.sh

जब आप bashइसके बजाय उपयोग करते हैं source, तो स्क्रिप्ट मूल स्क्रिप्ट के वातावरण को बदल नहीं सकती है। .आदेश POSIX मानक है, जबकि sourceआदेश के लिए एक अधिक पठनीय बैश पर्याय है .(मैं पसंद sourceसे अधिक .)। यदि आपकी लिपि कहीं और बसती है तो उस लिपि को पथ प्रदान करें। दोनों रिश्तेदार और साथ ही पूर्ण पथ को काम करना चाहिए।


5

शीर्ष उत्तर #!/bin/bashउप-स्क्रिप्ट की पहली पंक्ति में लाइन जोड़ने का सुझाव देता है । लेकिन भले ही आप शेबंग जोड़ते हैं, एक उप-शेल में स्क्रिप्ट चलाने और आउटपुट कैप्चर करने के लिए यह बहुत तेज़ है * :

$(source SCRIPT_NAME)

यह तब काम करता है जब आप एक ही दुभाषिया (जैसे बैश से दूसरी बैश स्क्रिप्ट) को चलाते रहना चाहते हैं और यह सुनिश्चित करते हैं कि सब-स्क्रिप्ट की शेलबैंग लाइन निष्पादित नहीं होती है।

उदाहरण के लिए:

#!/bin/bash
SUB_SCRIPT=$(mktemp)
echo "#!/bin/bash" > $SUB_SCRIPT
echo 'echo $1' >> $SUB_SCRIPT
chmod +x $SUB_SCRIPT
if [[ $1 == "--source" ]]; then
  for X in $(seq 100); do
    MODE=$(source $SUB_SCRIPT "source on")
  done
else
  for X in $(seq 100); do
    MODE=$($SUB_SCRIPT "source off")
  done
fi
echo $MODE
rm $SUB_SCRIPT

आउटपुट:

~ ❯❯❯ time ./test.sh
source off
./test.sh  0.15s user 0.16s system 87% cpu 0.360 total

~ ❯❯❯ time ./test.sh --source
source on
./test.sh --source  0.05s user 0.06s system 95% cpu 0.114 total

* उदाहरण के लिए जब वायरस या सुरक्षा उपकरण किसी उपकरण पर चल रहे हों तो नई प्रक्रिया को क्रियान्वित करने में अतिरिक्त 100ms लग सकते हैं।



4
 #!/bin/bash

 # Here you define the absolute path of your script

 scriptPath="/home/user/pathScript/"

 # Name of your script

 scriptName="myscript.sh"

 # Here you execute your script

 $scriptPath/$scriptName

 # Result of script execution

 result=$?

1
रिक्त स्थान के साथ फ़ोल्डर scriptPathया फ़ाइल नाम के लिए गलतscriptName
आंद्रेई कर्सुटस्की

3

मान लें कि नई फ़ाइल "/ home / satya / app / app_specific_env" है और फ़ाइल सामग्री इस प्रकार है:

#!bin/bash

export FAV_NUMBER="2211"

इस फ़ाइल संदर्भ को ~ / .bashrc फ़ाइल में जोड़ें

source /home/satya/app/app_specific_env

जब भी आप मशीन या फिर से शुरू करते हैं, echo $FAV_NUMBERतो टर्मिनल में देखें। यह मूल्य का उत्पादन करेगा।

बस अगर आप तुरंत प्रभाव देखना चाहते हैं, source ~/.bashrcतो कमांड लाइन में।


3
chmod a+x /path/to/file-to-be-executed

मुझे केवल यही चाहिए था। एक बार स्क्रिप्ट निष्पादित करने के लिए इस तरह निष्पादन किया जाता है, तो आप (मेरे मामले में कम से कम) की तरह किसी भी अन्य अतिरिक्त आपरेशन की जरूरत नहीं है shया./ जब तुम स्क्रिप्ट बुला रहे हैं।

@Nathan लिलिएनथाल की टिप्पणी के लिए धन्यवाद


1

अन्य फ़ाइल से फ़ंक्शंस आयात करने में कुछ समस्याएं हैं।
पहला : आपको इस फ़ाइल को निष्पादन योग्य बनाने की आवश्यकता नहीं है। बेहतर है कि ऐसा न करें! बस जोड़ दो

. file

सभी कार्यों को आयात करने के लिए। और ये सभी ऐसे होंगे जैसे कि वे आपकी फाइल में परिभाषित हैं।
दूसरा : आप फ़ंक्शन को उसी नाम से परिभाषित कर सकते हैं। इसे ओवरराइट किया जाएगा। यह बुरा है। आप इस तरह की घोषणा कर सकते हैं

declare -f new_function_name=old_function_name 

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


(अतः आपका स्वागत है!) के रूप में उपयोगकर्ता प्रवीण पिछले 2011 में देखा गया था, यह सुलझाने के लिए है कि क्या सवाल था मुश्किल हो के लिए बाध्य है कैसे खोल क्रियान्वित करने के लिए a.sh निष्पादित b.sh (और क्रियान्वित जारी a.sh नहीं तो अन्यथा आज्ञा दी ), या शाब्दिक रूप से b.sh को कॉल करें । (मेरी वर्तनी की जाँच करने वाला पकड़ नहीं पाता है bush versions।) (क्या आपके पास अंग्रेजी व्याकरण में आपकी मदद करने के लिए कोई है? (कभी-कभी मेरी इच्छा थी।))
greybeard

0

बैकटिक्स का प्रयोग करें।

$ ./script-that-consumes-argument.sh `sh script-that-produces-argument.sh`

फिर उपभोक्ता स्क्रिप्ट पर एक तर्क के रूप में निर्माता स्क्रिप्ट का आउटपुट प्राप्त करें।

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