Wie führe ich ein Shell-Skript auf einer Unix-Konsole oder einem Mac-Terminal aus?

507

Ich weiß es, vergesse es und lerne es wieder. Zeit, es aufzuschreiben.

PA
quelle
15
Schreiben Sie den Upvote-Zug bis zur Reputationsstation
DivideByZer0
Ich werde nicht nur dafür stimmen, um diesen großartigen Fehler zu bewundern, den du dort bekommen hast!
BRHSM

Antworten:

942

shVerwenden Sie zum Ausführen eines nicht ausführbaren Skripts:

sh myscript

bashVerwenden Sie zum Ausführen eines nicht ausführbaren Skripts:

bash myscript

So starten Sie eine ausführbare Datei (eine Datei mit ausführbarer Berechtigung); Sie geben es einfach durch seinen Pfad an:

/foo/bar
/bin/bar
./bar

Um ein Skript ausführbar zu machen, geben Sie ihm die erforderliche Berechtigung:

chmod +x bar
./bar

Wenn eine Datei ausführbar ist, ist der Kernel dafür verantwortlich, herauszufinden, wie sie ausgeführt werden soll. Bei Nicht-Binärdateien erfolgt dies in der ersten Zeile der Datei. Es sollte enthalten hashbang:

#! /usr/bin/env bash

Der Hashbang teilt dem Kernel mit, welches Programm ausgeführt werden soll (in diesem Fall wird der Befehl /usr/bin/envmit dem Argument ausgeführt bash). Anschließend wird das Skript zusammen mit allen Argumenten, die Sie dem Skript als nachfolgende Argumente gegeben haben, an das Programm übergeben (als zweites Argument).

Das bedeutet, dass jedes ausführbare Skript einen Hashbang haben sollte . Wenn dies nicht der Fall ist, sagen Sie dem Kernel nicht, was es ist , und daher weiß der Kernel nicht, mit welchem ​​Programm er es interpretieren soll. Es könnte sein bash, perl, python, sh, oder etwas anderes. (In der Realität verwendet der Kernel häufig die Standard-Shell des Benutzers, um die Datei zu interpretieren. Dies ist sehr gefährlich, da er möglicherweise überhaupt nicht der richtige Interpreter ist oder einige davon analysieren kann, jedoch subtile Verhaltensunterschiede aufweist der Fall zwischen shund bash).

Ein Hinweis zu /usr/bin/env

Am häufigsten sehen Sie Hash-Pony wie folgt:

#!/bin/bash

Das Ergebnis ist, dass der Kernel das Programm /bin/bashausführt, um das Skript zu interpretieren. Leider bashwird nicht immer standardmäßig ausgeliefert, und es ist nicht immer in verfügbar /bin. Während dies normalerweise auf Linux-Computern der Fall ist, gibt es eine Reihe anderer POSIX-Computer, auf denen bashSchiffe an verschiedenen Orten ausgeliefert werden, z. B. /usr/xpg/bin/bashoder /usr/local/bin/bash.

Um ein portables Bash-Skript zu schreiben, können wir uns daher nicht darauf verlassen, den Speicherort des bashProgramms fest zu codieren . POSIX hat bereits einen Mechanismus, um damit umzugehen : PATH. Die Idee ist, dass Sie Ihre Programme in einem der Verzeichnisse installieren, in denen sich PATHdas System befindet, und dass das System Ihr Programm finden kann, wenn Sie es namentlich ausführen möchten.

Leider können Sie dies nicht einfach tun:

#!bash

Der Kernel wird (einige könnten) keine PATHSuche für Sie durchführen. Es gibt ein Programm, das eine PATHSuche für Sie durchführen kann, es heißt jedoch env. Glücklicherweise ist auf fast allen Systemen ein envProgramm installiert /usr/bin. Daher verwenden wir enveinen fest codierten Pfad, der dann nach ihm PATHsucht bashund ihn ausführt, damit er Ihr Skript interpretieren kann:

#!/usr/bin/env bash

Dieser Ansatz hat einen Nachteil: Laut POSIX kann der Hashbang ein Argument haben . In diesem Fall verwenden wir bashals Argument für das envProgramm. Das heißt, wir haben keinen Platz mehr, an den wir Argumente übergeben können bash. Es gibt also keine Möglichkeit, so etwas #!/bin/bash -exuin dieses Schema umzuwandeln . Sie müssen set -exustattdessen nach dem Hashbang setzen.

Dieser Ansatz hat noch einen weiteren Vorteil: Einige Systeme werden möglicherweise mit einem ausgeliefert /bin/bash, aber der Benutzer mag ihn möglicherweise nicht, findet ihn möglicherweise fehlerhaft oder veraltet und hat möglicherweise seinen eigenen an einem bashanderen Ort installiert . Dies ist häufig unter OS X (Macs) der Fall, wo Apple ein veraltetes /bin/bashProdukt ausliefert und Benutzer /usr/local/bin/bashmithilfe von Homebrew ein aktuelles Gerät installieren . Wenn Sie den envAnsatz verwenden, der eine PATHSuche durchführt, berücksichtigen Sie die Präferenzen des Benutzers und verwenden seine bevorzugte Bash gegenüber der, mit der sein System geliefert wurde.

lhunath
quelle
66
Vielen Dank, dass Sie sich die Zeit genommen haben, eine gute Antwort auf eine einfache Frage zu schreiben.
PA
5
Wenn ich zshals Shell verwenden würde, würde ich die verwenden hashbang #! /usr/bin/env zsh?
Stefmikhail
6
@stefmikhail: Es spielt keine Rolle, welchen Shell-Interpreter Sie zum Aufrufen des Skripts verwenden. Sie sollten verwenden, #! /usr/bin/env zshwenn (und nur wenn) der Code im Skript von der Z-Shell ausgeführt werden soll.
Johnsyweb
1
+1 zur Erklärung. Ich neige dazu zu vergessen, aber wenn ich die Bedeutung des Befehls kenne, kann ich mich besser erinnern.
Angelin Nadar
2
@Carpetsmoker Dies ist korrekt und nicht auf den Hashbang beschränkt. Bash-Skripte sollten immer UNIX-Zeilenenden verwenden, da an das letzte Argument jedes Befehls ein \ r angehängt wird, genau wie der Name des Hashbang-Befehls.
lhunath
80

So starten Sie das Shell-Skript 'file.sh':

sh file.sh

bash file.sh

Eine weitere Option ist das Festlegen der ausführbaren Berechtigung mit dem Befehl chmod:

chmod +x file.sh

Führen Sie nun die .sh-Datei wie folgt aus:

./file.sh
PA
quelle
16

Für die Bourne Shell:

sh myscript.sh

Für Bash:

bash myscript.sh

quelle
Vielen Dank für die Beantwortung dieser ganz offensichtlichen Frage. Für einen Mac wie mich ist es leicht, die alten Unix-Befehle zwischen den Runden zu vergessen.
PA
10

Wenn Sie möchten, dass das Skript in der aktuellen Shell ausgeführt wird (z. B. möchten Sie, dass es sich auf Ihr Verzeichnis oder Ihre Umgebung auswirkt), sollten Sie Folgendes sagen:

. /path/to/script.sh

oder

source /path/to/script.sh

Beachten Sie, dass /path/to/script.shrelativ sein kann, zum Beispiel . bin/script.shläuft die script.shin dem binVerzeichnis unter dem aktuellen Verzeichnis.

Chas. Owens
quelle
7
Seien Sie sehr vorsichtig, wenn Sie mit verwandten Pfadnamen suchen oder punktieren. Sie sollten sie immer mit ./ beginnen. Wenn Sie dies nicht tun und der relative Pfadname keine Schrägstriche enthält, suchen Sie etwas in PATH, BEVOR etwas im aktuellen Verzeichnis! Sehr gefährlich für Missbrauch.
lhunath
0

Geben Sie zunächst die Erlaubnis zur Ausführung: -
chmod +x script_name

  1. Wenn das Skript nicht ausführbar ist: -
    Zum Ausführen der sh-Skriptdatei: -
    sh script_name
    Zum Ausführen der Bash-Skriptdatei: -
    bash script_name
  2. Wenn das Skript ausführbar ist: -
    ./script_name

HINWEIS : - Mit 'ls -a' können Sie überprüfen, ob die Datei ausführbar ist oder nicht.

Vineet Jain
quelle
0

Die Dateierweiterung .command wird Terminal.app zugewiesen. Durch Doppelklicken auf eine Befehlsdatei wird diese ausgeführt.

benwiggy
quelle
0

Kleine Ergänzung, um einen Interpreter aus demselben Ordner auszuführen und weiterhin #! Hashbang in Skripten zu verwenden.

Als Beispiel befindet sich eine ausführbare Datei von php7.2, die aus / usr / bin kopiert wurde, in einem Ordner entlang eines Hallo- Skripts.

#!./php7.2
<?php

echo "Hello!"; 

Um es auszuführen:

./hello

Welche sich genauso verhalten wie:

./php7.2 hello
NVRM
quelle