Wie rufe ich ein Shell-Skript von einem anderen Shell-Skript auf?

739

Ich habe zwei Shell-Skripte, a.sh und b.sh.

Wie kann ich b.shaus dem Shell-Skript heraus aufrufen a.sh?

Praveen
quelle
8
Können Sie einige Details angeben: Welches Betriebssystem und welche Shell (s) oder sprechen Sie im Prinzip nur über dieses Problem? Beispielcode wäre ebenfalls hilfreich.
jsalonen
14
Dies ist weder eine spezifische Frage noch zeigt sie vorherige Anstrengungen zur Lösung des Problems.
Kris
1
Ein Problem, das ich hatte, war, dass ich b.shkeine ausführbaren Berechtigungen hatte. Es könnte eine gute Sache sein, dies zu überprüfen.
Seth10
Fügen Sie ./stattdessen vor dem b.sh./b.sh
Benny
1
Wenn jemand immer wieder den No such file or directoryFehler stackoverflow.com/a/2920431/1356559
Amr Lotfy

Antworten:

959

Es gibt verschiedene Möglichkeiten, dies zu tun:

  1. Machen Sie das andere Skript ausführbar, fügen Sie die #!/bin/bashZeile oben und den Pfad, in dem sich die Datei befindet, zur Umgebungsvariablen $ PATH hinzu. Dann können Sie es als normalen Befehl aufrufen;

  2. Oder rufen Sie es mit dem sourceBefehl (Alias ​​ist .) wie folgt auf : source /path/to/script;

  3. Oder verwenden Sie den bashBefehl, um es auszuführen : /bin/bash /path/to/script;

Die erste und dritte Methode führen das Skript als einen anderen Prozess aus, sodass auf Variablen und Funktionen im anderen Skript nicht zugegriffen werden kann.
Die zweite Methode führt das Skript im Prozess des ersten Skripts aus und ruft Variablen und Funktionen aus dem anderen Skript ab, damit sie aus dem aufrufenden Skript verwendet werden können.

Wenn Sie in der zweiten Methode das exitzweite Skript verwenden, wird auch das erste Skript beendet. Was bei der ersten und dritten Methode nicht passieren wird.

Einige Programmierer
quelle
30
chmod a+x /path/to/fileDenken Sie daran, sonst wird es nicht ausführbar sein. Gilt nur für die ./script-Methode.
Nathan Lilienthal
3
Denken Sie daran, das Format / die Codierung ausführbarer Dateien unter Unix zu ändern, wenn diese unter DOS erstellt und dann in die Unix-Umgebung hochgeladen werden -> dos2unix <Skriptname>
Abhishek Chatterjee
3
@cecemel Der erste und dritte Weg könnte "asynchron" sein, indem die normale Run-In-Background-Syntax verwendet wird.
Einige Programmierer Typ
16
Das Problem dabei sourceist, dass eine exitAnweisung im aufgerufenen Skript auch Ihre beendet ...
Ohad Schneider
18
@ user528025 .ist kein Alias ​​für source, sondern umgekehrt. sourceist eine Bash-Erweiterung und .funktioniert in jeder POSIX-kompatiblen Shell.
Score_Under
207

Überprüfen Sie dies heraus.

#!/bin/bash
echo "This script is about to run another script."
sh ./script.sh
echo "This script has just run another script."
Budha
quelle
4
Dies setzt voraus, dass sich script.sh im selben Verzeichnis befindet wie das Skript, das gerade ausgeführt wird. Wenn Sie ein Skript woanders aufrufen möchten, würden Sie sagensh <path to script>/script.sh
Morgan Kenyon
32
Dies verwendet auch zwei Schalen bashund sh. Selbst wenn shes tatsächlich bashso ist, verhält es sich nicht gleich. Wenn Sie verwenden #!/bin/bash, möchten Sie wahrscheinlich verwenden bash script.sh(oder nur ./script.shden Hashbang dieses Skripts verwenden).
Martin Tournoij
1
Fehler beim Abrufen der Berechtigung, auch wenn ich chmod +xdie .sh-Datei festgelegt habe. Irgendwelche Vorschläge?
Isaac Wetter
@isaacweathers versuchen chmod 777
Janac Meena
114

Es gibt verschiedene Möglichkeiten, dies zu tun. Terminal zum Ausführen des Skripts:

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

All dies ist richtig für den Pfad mit Leerzeichen !!!

Andrei Krasutski
quelle
41
Was sind ihre Unterschiede? Warum einer, warum ein anderer?
Raketenabstandhalter
. "$ SCRIPT_PATH" wird bevorzugt
Harry Mumford-Turner
1
Ich kann nur hinzufügen, dass diese nicht alle gleichwertig sind, z. B. sh "$ SCRIPT_PATH" und bash "$ SCRIPT_PATH" führen kein #! / Usr / bin / expected-Skript aus, während nur "$ SCRIPT_PATH" dies tut.
Tahlor
58

Die Antwort, nach der ich gesucht habe:

( exec "path/to/script" )

Ersetzt wie erwähnt execdie Shell, ohne einen neuen Prozess zu erstellen. Allerdings können wir es in einer Subshell setzen, die die Klammern aus geschehen würde .

EDIT: Eigentlich ( "path/to/script" )ist genug.

Maxim Chetrusca
quelle
11
Das scheint ziemlich verworren zu sein. Warum nicht einfach mit anrufen /path/to/script? Ich sehe hier überhaupt keine Notwendigkeit exec?
Martin Tournoij
Die Unterschale wird auch nicht benötigt, da Sie nicht arbeiten exec.
Karel Vlk
6
Wie würden Sie dieses Skript mit Argumenten ausführen?
Bhargav
Wenn Sie die Ausgabe des
Unterskripts
@ Bhargav folgen Sie diesem Link stackoverflow.com/questions/14302389/…
tpbafk
16

Kommt drauf an. Kurz ... Wenn Sie Variablen auf die aktuelle Konsole laden und ausführen möchten, können Sie sie source myshellfile.shfür Ihren Code verwenden. Beispiel:

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

Wenn Sie nur eine Datei ausführen möchten und das Ergebnis nur für Sie interessant ist, können Sie Folgendes tun:

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

Ich hoffe es hilft dir. Vielen Dank.

Douglas Bonafé
quelle
2
Beachten Sie, dass dies sourceeine Bash-spezifische Funktion ist. Die Standard-Bourne-Shell hat nur .(zB . other_script.sh).
Martin Tournoij
15

Sie können ein /bin/shanderes Skript aufrufen oder ausführen (über Ihr eigentliches Skript):

 # 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

Die Ausgabe wäre:

 # ./mainscript.sh
 You are login as: root
 Date is: Thu Oct 17 02:56:36 EDT 2013
Ranjithkumar T.
quelle
1
Sicherlich läuft dies showdate.shunter / bin / sh und nicht unter / bin / bash?
Chris Watts
Ich habe es mit " /bin/sh ./showdate.sh", " /bin/bash ./showdate.sh", " ./showdate.sh" versucht und die Datei: mainscript.sh ausgeführt und die gleiche Ausgabe erhalten.
Ranjithkumar T
10

Fügen Sie einfach in eine Zeile ein, was auch immer Sie in ein Terminal eingegeben hätten, um das Skript auszuführen!
z.B:

#!bin/bash
./myscript.sh &

Wenn sich das auszuführende Skript nicht im selben Verzeichnis befindet, verwenden Sie einfach den vollständigen Pfad des Skripts.
Beispiel: `/ home / user / script-directory /./ myscript.sh &

Anon
quelle
@ Carpetsmoker &für Hintergrundaufgabe
Andrei Krasutski
9

Zuerst müssen Sie die aufgerufene Datei einschließen:

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

dann rufen Sie Ihre Funktion folgendermaßen auf:

#!/bin/bash
my_called_function
Ghazi Triki
quelle
9

Einfache Quelle wird Ihnen helfen. Zum Beispiel.

#!/bin/bash
echo "My shell_1"
source my_script1.sh
echo "Back in shell_1"
Nitin Jawarkar
quelle
9

Wenn Sie eine andere Datei im selben Verzeichnis haben, können Sie Folgendes tun:

bash another_script.sh

oder

source another_script.sh

oder

. another_script.sh

Wenn Sie bashanstelle von verwenden source, kann das Skript die Umgebung des übergeordneten Skripts nicht ändern. Der .Befehl ist POSIX - Standard , während sourceBefehl ein lesbares bash Synonym für ist .(ich ziehe sourceüber .). Wenn sich Ihr Skript an einer anderen Stelle befindet, geben Sie einfach den Pfad zu diesem Skript an. Sowohl der relative als auch der vollständige Pfad sollten funktionieren.

Shital Shah
quelle
5

In der oberen Antwort #!/bin/bashwird vorgeschlagen, der ersten Zeile des aufgerufenen Unterskripts eine Zeile hinzuzufügen . Aber selbst wenn Sie den Shebang hinzufügen, ist es viel schneller * , ein Skript in einer Sub-Shell auszuführen und die Ausgabe zu erfassen:

$(source SCRIPT_NAME)

Dies funktioniert, wenn Sie weiterhin denselben Interpreter ausführen möchten (z. B. von Bash zu einem anderen Bash-Skript) und sicherstellen möchten, dass die Shebang-Zeile des Unterskripts nicht ausgeführt wird.

Zum Beispiel:

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

Ausgabe:

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

* Wenn beispielsweise Viren- oder Sicherheitstools auf einem Gerät ausgeführt werden, kann die Ausführung eines neuen Prozesses zusätzliche 100 ms dauern.

cmcginty
quelle
4
pathToShell="/home/praveen/"   
chmod a+x $pathToShell"myShell.sh"
sh $pathToShell"myShell.sh"
Abdennour TOUMI
quelle
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=$?
Valero
quelle
1
falsch für Ordner- scriptPathoder Dateinamen scriptNamemit Leerzeichen
Andrei Krasutski
3

Angenommen, die neue Datei lautet "/ home / satya / app / app_specific_env" und der Dateiinhalt lautet wie folgt

#!bin/bash

export FAV_NUMBER="2211"

Hängen Sie diesen Dateiverweis an die Datei ~ / .bashrc an

source /home/satya/app/app_specific_env

Wenn Sie den Computer neu starten oder neu anmelden, versuchen Sie es echo $FAV_NUMBERim Terminal. Der Wert wird ausgegeben.

Nur für den Fall, dass Sie den Effekt sofort source ~/.bashrcin der Befehlszeile sehen möchten .

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

Das war das einzige was ich brauchte. Sobald das auszuführende Skript wie folgt ausführbar gemacht wurde, benötigen Sie (zumindest in meinem Fall) keine weitere zusätzliche Operation wie shoder./ während Sie das Skript aufrufen.

Danke an den Kommentar von @Nathan Lilienthal

Asqan
quelle
1

Es gibt einige Probleme beim Importieren von Funktionen aus anderen Dateien.
Erstens : Sie müssen diese Datei nicht ausführbar machen. Besser nicht! einfach hinzufügen

. file

um alle Funktionen zu importieren. Und alle werden so sein, als wären sie in Ihrer Datei definiert.
Zweitens : Möglicherweise definieren Sie die Funktion mit demselben Namen. Es wird überschrieben. Es ist schlecht. Sie können so erklären

declare -f new_function_name=old_function_name 

und erst danach importieren. Sie können also die alte Funktion mit einem neuen Namen aufrufen.
Drittens : Sie dürfen nur die vollständige Liste der in der Datei definierten Funktionen importieren. Wenn einige nicht benötigt werden, können Sie sie deaktivieren. Wenn Sie Ihre Funktionen jedoch nach dem Deaktivieren neu schreiben, gehen sie verloren. Wenn Sie jedoch wie oben beschrieben darauf verweisen, können Sie nach dem Deaktivieren mit demselben Namen wiederherstellen.
SchließlichIm allgemeinen Verfahren ist der Import gefährlich und nicht so einfach. Achtung! Sie können ein Skript schreiben, um dies einfacher und sicherer zu machen. Wenn Sie nur einen Teil der Funktionen (nicht alle) verwenden, teilen Sie diese besser in verschiedene Dateien auf. Leider ist diese Technik in Bash nicht gut gemacht. In Python zum Beispiel und einigen anderen Skriptsprachen ist es einfach und sicher. Es ist möglich, nur benötigte Funktionen mit eigenen Namen teilweise zu importieren. Wir alle möchten, dass in den nächsten Buschversionen die gleiche Funktionalität ausgeführt wird. Aber jetzt müssen wir viele zusätzliche Kabeljau schreiben, um zu tun, was Sie wollen.

Anatoly
quelle
(Willkommen bei SO!) Da Benutzer Praveen zuletzt im Jahr 2011 gesehen wurde, ist es sicherlich schwierig herauszufinden, ob die Frage lautete, wie die Shell a.sh ausführen soll , um b.sh auszuführen (und a.sh weiter auszuführen, wenn nicht anders befohlen ) oder buchstäblich b.sh aufrufen . (Meine Rechtschreibprüfung fängt nicht bush versions.) (Haben Sie jemanden, an den Sie sich wenden können, um Ihnen bei der englischen Grammatik zu helfen? (Manchmal wünschte ich, ich hätte es
getan
0

Verwenden Sie Backticks.

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

Rufen Sie dann die Ausgabe des Producer-Skripts als Argument für das Consumer-Skript ab.

Dacabdi
quelle