.sh spezifizierende Erweiterung?

12

Warum wird auf einigen Systemen eine .shDatei nur durch Angabe des Dateinamens ohne Erweiterung ausgeführt, und für andere wird Name plus Erweiterung benötigt? In meinem Fall versuche ich, eine Reihe von Befehlen zu schreiben, die diesen Anweisungen folgen .

Ich gebe jetzt die Erweiterung an, aber es .shwäre besser, wenn ich die Befehle ohne ausführen könnte.

Philip Kirkbride
quelle
4
Die Verwendung .shals Erweiterung wird unter vielen Umständen als schlechte Praxis angesehen: Es ist im Gegensatz zu den Namen anderer Befehle (die Sie nicht ausführen ls.elf) oft irreführend (wenn Sie foo.shmit beginnen #!/bin/bash, sh foo.shwird sie beim Ausführen mit einem anderen Interpreter ausgeführt, als für den sie erstellt wurde ), und wenn Sie neu schreiben foo.sh, um ein Python-Programm zu sein, müssen Sie bei der Verwendung dieser Erweiterung zwischen der Beibehaltung des jetzt irreführenden Namens und dem erneuten Schreiben jedes Programms wählen, das ihn aufruft.
Charles Duffy
2
... wo es ist eine bewährte Methode Shell - Bibliotheken ist, nicht mit Befehlen +xset - wo foo.sheine Bibliothek ist , die in jede POSIX - Shell gezogen werden kann, foo.bashkann in bash, bezogen werden foo.kshin ksh etc.
Charles Duffy

Antworten:

39

Du bist verwirrt. Die .shErweiterung ist nur ein Hinweis für den Menschen und hat keinerlei Einfluss darauf, wie das System mit der Datei umgeht. Unix / Linux hat den Windows- Secrets.pdf.exeFehler nicht verursacht.

Folgendes passiert beim Tippen foo:

  1. Umleitung für STDIN, STDOUTund STDERReingerichtet sind.

  2. Die Shell überprüft ihre interne Hash-Tabelle, um festzustellen, ob sie bereits einen $PATHEintrag für kennt foo. Ist dies nicht der Fall, durchsucht die Shell die Verzeichnisse $PATHnach einer Datei foo, deren Dateiberechtigungen das Ausführungsbit enthalten. Erster foogewinnt.

  3. Wenn die ersten beiden Bytes der Datei vorhanden foosind #!, ist die nächste Zeichenfolge der Name eines auszuführenden Interpreters. Führt also #!/bin/bashein Bash-Skript, #!/usr/bin/perlein Perl-Skript usw. ein.

  4. Wenn die Datei mit beginnt \177ELF, ist sie eine ausführbare Binärdatei und ld.sostartet sie.

Lesen Sie man execveund man ld.sofür eine detailliertere Erklärung.

Waltinator
quelle
15
Ja, unter Linux können Sie auf Secrets.pdf doppelklicken, ohne einen Hinweis darauf zu haben, dass es sich tatsächlich um eine ausführbare Datei handelt;)
OrangeDog
1
@OrangeDog Ich weiß, dass Sie Witze machen, aber ich habe das Gefühl, dass ich darauf hinweisen muss, dass das ausführbare Bit ( chmod +x) dies so ziemlich löst, oder?
Wchargin
3
@WChargin Das hängt davon ab, wie gut sich Ihr Dateisystem verhält (z. B. eine gemountete Netzwerkfreigabe oder eine NTFS-Partition setzt das xBit auf alles) und woher die Datei stammt (jeder Prozess mit Kontrolle über das Verzeichnis könnte dazu verleitet werden, die Berechtigungen festzulegen). . Also, es mildert es, aber ich würde nicht sagen, dass es es löst .
IMSoP
2
@WChargin, aber ich denke sein Punkt, dass in der Regel Dateimanager das ausführbare Bit nicht anzeigen, dh es gibt keinen "Hinweis auf Menschen" wie eine Erweiterung.
Paul Draper
1
Ich habe nie versehentlich auf Secrets.pdf.exehide file extension
geklickt,
12

Der entscheidende Punkt ist: Erweiterungen sind in jedem Unix-ähnlichen Systemsystem irrelevant. Ein Dateiname ist nur ein Name und hat keine Auswirkung darauf, ob ein Skript oder eine kompilierte ausführbare Datei ausgeführt werden kann . Ein Programmierer kann eine .shErweiterung hinzufügen , .pyum anzugeben, dass es sich bei einer Datei um ein Shell-Skript oder um ein Python-Skript handelt. Im Gegensatz zu Windows kümmert sich ein Unix nicht um die Benennung, sondern um Berechtigungen.

Was zählt, ist die ausführbare Berechtigung, die einer Datei erteilt wird. Was Sie mit überprüfen können

ls -l /path/to/file

Ausführen von ausführbaren Dateien

Es gibt im Allgemeinen mehrere Möglichkeiten, ein Skript auszuführen.

  • Wenn Ihr aktuelles Verzeichnis mit dem Skript identisch ist und das Skript über ausführbare Berechtigungen verfügt, können Sie es wie folgt ausführen ./my_script_name. Das .bedeutet aktuelles Verzeichnis.
  • Wenn sich Ihr aktuelles Verzeichnis unterscheidet und das Skript über ausführbare Berechtigungen verfügt, können Sie es ausführen, indem Sie den vollständigen Pfad angeben: /home/user/bin/my_script_name

(Die beiden oben genannten Methoden setzen voraus, dass die ausführbare Berechtigung festgelegt ist. Ob die Datei Teil der $PATHVariablen ist oder nicht , spielt keine Rolle. Das Vorhandensein der #!Zeile ist ebenfalls wichtig. Ohne diese Option wird das Skript von der aktuellen Shell ausgeführt, die Sie geöffnet haben. Wenn ich ein cshSkript habe ohne diese Zeile, und versuchen Sie, es in bash mit auszuführen ./my_script.csh, wird es fehlschlagen)

  • Befindet sich Ihr Skript in einem Verzeichnis, das Teil Ihrer $PATHVariablen ist, können Sie es einfach durch Aufrufen des Namens ausführen. Sie können den chmodBefehl in der Befehlszeile aufrufen, indem Sie einfach seinen Namen eingeben, da er sich in einem /binOrdner befindet. /binist immer Teil der $PATHVariablen. In diesem Fall spielen ausführbare Berechtigungen und der Speicherort des Skripts eine Rolle
  • Angabe eines Interpreters als Befehl und eines Skripts als Argument. Auf diese Weise wird das Skript als Eingabedatei für den Interpreter verwendet.
  • Beschaffung einer Datei. Das . filename.shoder source filename.shbewirkt, dass das Skript so behandelt wird, als wäre es eine Tastatureingabe, dh als wäre es direkt in die Befehlszeile eingegeben worden. In diesem Fall spielen ausführbare Berechtigungen und der Speicherort keine Rolle

Beispiele

Beispiel # 1, ausgeführt mit einem Interpreter, um Berechtigungen auszuführen

$-> ls -l abc.py                                                               
-rw-rw-r-- 1 xieerqi xieerqi 44 Apr 27 22:39 abc.py
$-> python abc.py                                                              
a
b
c

Beispiel # 2, ausgeführt mit ./ausführbarem Berechtigungssatz, Shebang Line Set.

$-> cat abc.py                                                                 
#!/usr/bin/env python
for letter in 'a' 'b' 'c' :
   print letter
$-> ls -l abc.py
-rwxrwxr-x 1 xieerqi xieerqi 66 Apr 27 23:02 abc.py*
$-> ./abc.py                                                                   
a
b
c

Beispiel # 3, läuft ohne Shebang-Line-Set

$-> cat abc.py                                                                 
for letter in 'a' 'b' 'c' :
   print letter
$-> ./abc.py                                                                   
./abc.py: 2: ./abc.py: Syntax error: word unexpected (expecting "do")

Beispiel 4: Ausführen eines Skripts mit festgelegten ausführbaren Berechtigungen für einen Ordner, der Teil einer $PATHVariablen ist

#  /home/xieerqi/bin is part of my path variable
$-> echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/opt/microchip/xc16/v1.25/bin:/opt/microchip/xc32/v1.40/bin:/opt/microchip/xc8/v1.35/bin:/home/xieerqi/bin:/home/xieerqi/bin/sh

$-> # current directory is /home/xieerqi
$-> pwd
/home/xieerqi
$-> # move the file to ~/bin
$-> mv ~/abc.py ~/bin/abc.py
$-> # now I can run it just by calling the name
$-> abc.py
/home/xieerqi/bin/abc.py: 2: /home/xieerqi/bin/abc.py: Syntax error: word unexpected (expecting "do")
$-> # Syntax error because again, no interpreter specified.                    
$-> # must add #!/usr/bin/env python
$-> vi /home/xieerqi/bin/abc.py          
$-> # after adding the line with vi text editor, we can run
$-> abc.py                                                                     
a
b
c

Beispiel 5, Erweiterung entfernen, wird weiterhin ausgeführt, da Erweiterungen keine Rolle spielen, aber Berechtigungen haben und Teil von $PATH:

$-> mv ~/bin/abc.py  ~/bin/abc                                                 
$-> abc
a
b
c
Sergiy Kolodyazhnyy
quelle
Ich habe den Befehl ausgeführt und bekomme das '-rwxr-x ---'. Was soll der Wert lesen und wie kann ich ihn ändern?
Philip Kirkbride
Oder sagst du, ich sollte einfach 'filename.sh' in 'filename' umbenennen?
Philip Kirkbride
1
@PhilipKirkbride Name ist irrelevant. Wie führen Sie Ihren Befehl aus? Wo ist es ? Ist das Verzeichnis Teil Ihres Verzeichnisses PATH?
Sergiy Kolodyazhnyy
@PhilipKirkbride Lassen Sie mich meine Antwort in einer Minute erweitern, um es klarer zu machen.
Sergiy Kolodyazhnyy
1
Schauen Sie sich an man chmod, wie Sie Berechtigungen festlegen
Nick Mertin
6

Gute Erklärungen hier schon. Ich wollte nur hinzufügen, dass Sie im Idealfall keine Dateierweiterungen für ausführbare Dateien verwenden sollten.

Normalerweise müssen Sie etwas relativ Leichtes tun und mit einem kleinen Shell-Skript beginnen. Mit der Zeit fügen Sie Ihrem Skript immer mehr Funktionen hinzu, bis es mit der Zeit nicht mehr zu warten ist oder Sie Funktionen benötigen, die Sie mit einem Shell-Skript nicht einfach erreichen können, und überlegen, dieses Shell-Skript in einer anderen Sprache (Python) umzuschreiben , perl, ...?).

Das Umschreiben von Grund auf wird in der Regel als Fehler angesehen, bei Skripten kann dies jedoch sinnvoll sein, da sie normalerweise nicht so umfangreich sind oder über zahlreiche Funktionen verfügen. Nehmen wir jedoch an, dass es möglich ist, in einer anderen Sprache von Grund auf neu zu schreiben und dabei die Funktionen und Parameter / Flags des ursprünglichen Shell-Skripts beizubehalten.

Benutzer dieses Skripts müssen sich dieser Sprachänderung nicht bewusst sein. Sie führen denselben Befehl weiter aus und arbeiten weiter.

Wenn Ihr Skript benannt wurde do-something.sh, kann es weiter existieren do-something.sh, aber jetzt ist es (zum Beispiel) in Python geschrieben, und daher ist Ihr erster Hinweis jetzt ein völlig irreführender.

Carlos Campderrós
quelle
4

Um Dateien ohne Dateierweiterung auszuführen, die Sie normalerweise nicht viel tun müssen, stellen Sie einfach sicher, dass Sie (im Fall von Bash-Skripten) die richtige Shebang-Zeile in der ersten Zeile haben:

#!/bin/bash

dann müssen Sie auch die Datei für das System ausführbar machen durch

chmod 755 yourfilename

Dies ist das gleiche wie bei chmod +x yourfilenameder Verwendung der Zahlen, die einfach erklärt werden.

Es ist ein Zahlentripel aus hinzugefügten Oktalen, die erste Zahl steht für den Benutzer, die zweite für die Gruppe und die dritte für andere, mehr dazu finden Sie hier .

Und wenn Sie sich im selben Verzeichnis wie Ihr Skript befinden, vergessen Sie nicht, ./wie folgt zu verwenden :

./yourfilename
Videonauth
quelle
Versuchte dies. Leider kein Unterschied zu den ursprünglichen Ergebnissen.
Philip Kirkbride
@PhilipKirkbride schau dir meine überarbeitete Antwort an, dies wird wahrscheinlich mehr Licht ins Dunkel bringen.
Videonauth
0

Das .sh-Suffix kann tatsächlich stören, da Sie zum Ausführen myscript.sh eingeben müssen, anstatt nur myscript, das nicht funktioniert. Nennen Sie es lieber "myscript" ohne das Suffix .sh, und eine schnelle Verwendung des Befehls "file" zeigt Ihnen, ob es sich um eine ausführbare Binärdatei (ELF-Format unter Linux), ein Shell-Skript oder eine andere Art von Skript handelt.

QDOS (schnelles und schmutziges Betriebssystem, später von IBM in "DOS" umbenannt, nachdem es von mirosoft raubkopiert und illegal an sie verkauft wurde) und andere billige Abzocke von CP / M, einschließlich Windows, vermischen all dies, da es auf diesen Systemen keine gibt So etwas wie Ausführungsberechtigungen für Dateien. Dies hat in den letzten 30-40 Jahren zu unzähligen Sicherheitslücken geführt. Tatsächlich habe ich vor ein paar Minuten gerade mehrere Junk-Mails mit einer in Tölpel eingeschlossenen Zip-Datei erhalten, die in MYPICTURE.JPG.zip umbenannt wurde :)

geschlafen
quelle