Bir kabuk betiğini başka bir kabuk betiğinden nasıl çağırırım?


739

İki kabuk betiğim var a.shve b.sh.

b.shKabuk betiğinin içinden nasıl arayabilirim a.sh?


8
Bazı özellikleri verebilir misiniz: hangi işletim sistemi ve hangi kabuk (lar) ya da sadece prensip olarak bu sorundan bahsediyorsunuz ?? Örnek kod da yardımcı olacaktır.
jsalonen

14
Bu gerçekten belirli bir soru değildir ve sorunu çözmek için önceden çaba göstermez.
Kris

1
Sahip olduğum bir sorun b.sh, yürütülebilir izinleri olmamasıydı. Kontrol etmek iyi bir şey olabilir.
seth10

./Komut dosyası adının önüne ekleyin , örneğin: şunu b.shkullanın:./b.sh
Benny

1
Birisi No such file or directoryhata almaya devam ederse stackoverflow.com/a/2920431/1356559
Amr Lotfy

Yanıtlar:


959

Bunu yapmanın birkaç farklı yolu vardır:

  1. Diğer komut dosyasını yürütülebilir yapın, #!/bin/bashen üstteki satırı ve dosyanın olduğu yolu $ PATH ortam değişkenine ekleyin . Sonra normal bir komut olarak adlandırabilirsiniz;

  2. Veya şu şekilde source(alias is .) komutuyla çağırın source /path/to/script:;

  3. Veya bashyürütmek için komutu kullanın /bin/bash /path/to/script:;

Birinci ve üçüncü yöntemler komut dosyasını başka bir işlem olarak yürütür, böylece diğer komut dosyasındaki değişkenlere ve işlevlere erişilemez.
İkinci yöntem, komut dosyasını ilk komut dosyasının işleminde yürütür ve diğer komut dosyasından değişkenleri ve işlevleri alır, böylece çağıran komut dosyasından kullanılabilirler.

İkinci yöntemde, exitikinci komut dosyasında kullanıyorsanız , ilk komut dosyasından da çıkacaktır. Bu birinci ve üçüncü yöntemlerde olmayacak.


30
hatırlayın chmod a+x /path/to/fileyoksa çalıştırılamaz. Yalnızca ./script yöntemi için geçerlidir.
Nathan Lilienthal

3
Onlar DOS oluşturulan ve daha sonra Unix ortamına yüklenen eğer unix çalıştırılabilir dosya kodlama / değişim formatına Hatırla -> dos2unix <script adı>
Abhishek Chatterjee

3
@cecemel Birinci ve üçüncü yol , normal arka planda çalışma sözdizimi kullanılarak "zaman uyumsuz" olabilir .
Bazı programcı ahbap

16
Sorun , çağrılan komut dosyasındaki sourcebir exitifadenin sizden de
çıkmasıdır

18
@ user528025 .bunun için bir takma ad sourcedeğil, başka bir yoldur. herhangi bir POSIX uyumlu kabukta sourceçalışırken bash uzantısıdır ..
21'de

207

Şuna bir bak.

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

4
Bu, script.sh dosyasının çalıştığı tüm komut dosyalarıyla aynı dizinde olduğunu varsayar. Senaryoyu başka bir yere çağırmak istersen şöyle derdinsh <path to script>/script.sh
Morgan Kenyon

32
Bu aynı zamanda iki mermi kullanır bashve sh. shAslında ne zaman olsa bile bashaynı şekilde davranmaz. Kullanıyorsanız, #!/bin/bashmuhtemelen kullanmak bash script.sh(veya yalnızca ./script.shbu komut dosyalarının karmaşasını kullanmak) istersiniz.
Martin Tournoij

1
chmod +x.Sh dosyasına ayarladığımda bile izin alma hatası reddedildi . Herhangi bir öneri?
isaac weathers

@isaacweathers denemek chmod 777
Janac Meena

114

Bunu yapmanın birkaç yolu vardır. Komut dosyasını yürütmek için terminal:

#!/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")

Bütün bunlar boşluklu yol için doğrudur !!!


41
Farklılıkları neler? Neden biri, neden başka?
rocketspacer

. "$ SCRIPT_PATH" tercih edilir
Harry Mumford-Turner

1
Ben sadece bunların eşdeğer olmadığını ekleyebilirim, örneğin sh "$ SCRIPT_PATH" ve bash "$ SCRIPT_PATH" #! / Usr / bin / wait komut dosyasını çalıştırmazken, sadece "$ SCRIPT_PATH" çalışacaktır.
Tahlor

58

Aradığım cevap:

( exec "path/to/script" )

Belirtildiği gibi exec, kabuğu yeni bir işlem oluşturmadan değiştirir. Bununla birlikte , parantezler kullanılarak yapılan bir alt kabuğa koyabiliriz.

EDIT: Aslında ( "path/to/script" )yeterlidir.


11
Bu oldukça kıvrımlı görünüyor. Neden sadece onu aramıyorsun /path/to/script? execBurada ihtiyacım yok mu?
Martin Tournoij

Alt kabuk da gerekmediğinden gerekmiyor exec.
Karel Vlk

6
bu betiği bağımsız değişkenlerle nasıl yürütürdünüz?
Bhargav

Alt betiğin çıktısını hala yakalamak istiyorsanız $ (source "path / to / script") komutunu deneyin
cmcginty

@Bhargav bu bağlantıyı takip et stackoverflow.com/questions/14302389/…
tpbafk

16

Bağlıdır. Kısaca ... Geçerli konsolda değişkenleri yüklemek ve yürütmek istiyorsanız source myshellfile.shkodunuzda kullanabilirsiniz . Misal:

!#/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

Sadece bir dosyayı yürütmek istiyorsanız ve sizin için intersting yapan tek şey sonuç ise:

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

Umarım size yardımcı olur. Teşekkürler.


2
Bunun sourcebash'a özgü bir özellik olduğunu unutmayın. Standart bourne kabuğunda sadece .(ör. . other_script.sh) Bulunur .
Martin Tournoij

15

/bin/shBaşka bir komut dosyasını çağırmak veya yürütmek için kullanabilirsiniz (gerçek komut dosyanız aracılığıyla):

 # 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

Çıktı:

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

1
Elbette bu showdate.sh/ bin / bash yerine / bin / sh altında çalışacaktır ?
Chris Watts

" /bin/sh ./showdate.sh", " /bin/bash ./showdate.sh", " ./showdate.sh" ile denedim ve dosyayı çalıştırın: mainscript.sh ve aynı çıktı var.
Ranjithkumar T

10

Senaryoyu çalıştırmak için bir terminale ne yazmış olursanız olun bir satır ekleyin!
Örneğin:

#!bin/bash
./myscript.sh &

yürütülecek komut dosyası aynı dizinde değilse, komut dosyasının tam yolunu kullanmanız yeterlidir.
örneğin: `/ home / kullanıcı / kod dizini /./ myscript.sh &


Arka &plan görevi için Chapetsmoker
Andrei Krasutski

9

Öncelikle aradığınız dosyayı eklemeniz gerekir:

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

sonra işlevinizi şöyle çağırırsınız:

#!/bin/bash
my_called_function

9

Basit kaynak size yardımcı olacaktır. Örn.

#!/bin/bash
echo "My shell_1"
source my_script1.sh
echo "Back in shell_1"

9

Aynı dizinde başka bir dosyanız varsa, aşağıdakilerden birini yapabilirsiniz:

bash another_script.sh

veya

source another_script.sh

veya

. another_script.sh

bashBunun yerine kullandığınızda source, komut dosyası üst komut dosyasının ortamını değiştiremez. .İse komut POSIX standarttır sourcekomut için daha okunabilir bash eşanlamlısıdır .(tercihim sourceüzerinde .). Betiğiniz başka bir yerde bulunuyorsa, o betiğe yol verin. Hem göreli hem de tam yol çalışmalıdır.


5

Üst yanıt, #!/bin/bashçağrılan alt komut dosyasının ilk satırına satır eklemenizi önerir . Ancak, shebang ekleseniz bile , bir alt kabukta bir komut dosyası çalıştırmak ve çıktıyı yakalamak çok daha hızlı * :

$(source SCRIPT_NAME)

Bu, aynı yorumlayıcıyı (örneğin bash'tan başka bir bash betiğine) çalıştırmak istediğinizde çalışır ve alt betiğin shebang satırının yürütülmemesini sağlar.

Örneğin:

#!/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

Çıktı:

~ ❯❯❯ 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

* Örneğin bir aygıtta virüs veya güvenlik araçları çalışırken yeni bir işlem yürütmek fazladan 100 ms sürebilir.


4
pathToShell="/home/praveen/"   
chmod a+x $pathToShell"myShell.sh"
sh $pathToShell"myShell.sh"

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
boşluklu klasör scriptPathveya dosya adı yanlışscriptName
Andrei Krasutski

3

Yeni dosyanın "/ home / satya / app / app_specific_env" olduğunu ve dosya içeriğinin aşağıdaki gibi olduğunu varsayalım

#!bin/bash

export FAV_NUMBER="2211"

Bu dosya referansını ~ / .bashrc dosyasına ekleyin

source /home/satya/app/app_specific_env

Makineyi yeniden başlattığınızda veya yeniden giriş yaptığınızda echo $FAV_NUMBERterminalde deneyin . Değeri çıktılar.

Etkiyi hemen source ~/.bashrckomut satırında görmek istiyorsanız .


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

İhtiyacım olan tek şey buydu. Yürütülecek komut dosyası bu şekilde yürütülebilir hale getirildikten sonra, (en azından benim durumumda) , komut dosyasını çağırırken shveya ./çağırırken başka bir ek işleme ihtiyacınız yoktur .

@Nathan Lilienthal yorumuna teşekkürler


1

İşlevleri başka bir dosyadan içe aktarmada bazı sorunlar var.
İlk olarak : Bu dosyayı yürütülebilir yapmanıza gerek yoktur. Bunu yapmamak daha iyi! sadece ekle

. file

tüm işlevleri içeri aktarmak için. Ve hepsi dosyanızda tanımlanmış gibi olacak.
İkincisi : Aynı isimde fonksiyon tanımlayabilirsiniz. Üzerine yazılacak. O kötü. Böyle beyan edebilirsin

declare -f new_function_name=old_function_name 

ve ancak bundan sonra içe aktarın. Böylece eski fonksiyonu yeni isimle çağırabilirsiniz.
Üçüncü olarak : Dosyada tanımlanan işlevlerin yalnızca tam listesini alabilirsiniz. Bazıları gerekmiyorsa onları kaldırabilirsiniz. Ancak, işlevlerinizi ayarlandıktan sonra yeniden yazarsanız kaybolurlar. Ancak, referansı yukarıda açıklandığı gibi ayarlarsanız, aynı adla ayarlandıktan sonra geri yükleyebilirsiniz.
En sonundaOrtak ithalat prosedürü tehlikeli ve o kadar basit değil. Dikkatli ol! Bunu daha kolay ve güvenli yapmak için komut dosyası yazabilirsiniz. Eğer fonksiyonların sadece bir kısmını (hepsini değil) kullanırsanız, bunları farklı dosyalara ayırın. Ne yazık ki bu teknik bash iyi yapamadı. Örneğin python ve diğer bazı script dillerinde kolay ve güvenlidir. Yalnızca kendi adlarıyla gerekli işlevleri kısmi içe aktarma imkanı. Hepimiz bir sonraki çalı sürümlerinde aynı işlevselliğin yapılmasını istiyoruz. Ama şimdi istediğini yapmak için birçok ek kod yazmalıyız.


(SO hoş geldiniz!) Kullanıcı olarak Praveen son 2011 yılında görülmüş, mesele, sıralamak zor olacağı kesindir kabuk yürütme nasıl a.sh yürütmek b.sh (ve yürütme devam A.Ş değilse aksi halde komut verildi ) veya b.sh kelimesini tam anlamıyla aramak için . (Yazım denetleyicim yakalamıyor bush versions.) (İngilizce dilbilgisi konusunda size yardımcı olacak biriniz var mı? (Bazen isterdim.))
greybeard

0

İğne kullanın.

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

Ardından, üretici komut dosyasının çıktısını tüketici komut dosyasında bir argüman olarak getirin.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.