Ich habe ein Shell-Skript, in dem ich einen Shebang hinzufügen möchte. Gegeben eine Variable wie folgt definiert:
SHEBANG="#!/bin/sh"
Meine Frage ist, ob ich diese Variable in einem anderen Skript wie diesem verwenden kann:
$SHEBANG
# other stuff...
export SHEBANG='#!/bin/tcsh'
und es mit message fehlschlägt,#!/bin/tcsh: No such file or directory
obwohl / bin / tcsh existiert.$SHEBANG
später in einem Bash- oder TCSh-Skript eine eigene Zeile einfügen oder sie interaktiv ausführen würden./bin/tcsh
ist ein gültiger Pfad, aber#!/bin/tcsh
nicht, es sei denn, Sie werden zufällig in ein Verzeichnis kopiert, in dem./#!
sich ein Verzeichnis oder ein Symlink befindet.Antworten:
Nein. Die Shebang-Zeile wird von Ihrem Kernel oder Ihrer Systembibliothek * verarbeitet und verarbeitet keine Shell-Variablen.
Wenn Sie aus irgendeinem Grund eine Umgebungsvariable als Interpreter verwenden möchten, können Sie eine ausführbare "Trampolin" -Datei (kein Skript!) Erstellen, die erneut erzeugt wird
$SHEBANG "$@"
.#!
In diesem Fall müssen Sie die Variable weglassen .#!
ist nur nützlich, wenn es buchstäblich die ersten zwei Bytes einer Datei sind.Eine andere Möglichkeit besteht darin, die Tatsache
sh
zu nutzen , dass Skripte ohne Shebang-Zeilen (im Allgemeinen) als Shell-Skripte mit einer oder der aufrufenden Shell ausgeführt werden . Wenn es eine Kommentarsyntax für Ihr Shebang-Ziel gibt, die sich sinnvoll mit der Shell-Syntax überschneidet, können Sie sie zum Laufen bringen. Diese Strategie ist oder war bei Lisp-Dolmetschern üblich. In Ihrem Beispiel, in dem sich auch der Interpreter befindetsh
, ist dies nicht möglich.Sie können die Dinge in dieser Zeile noch weiter vorantreiben, wenn Sie sich darauf verlassen können, dass
bash
sie vorhanden sind: ein Skript, dessen erste Zeile lautetwird für die meisten Dolmetscher funktionieren; Bash wird als Zwischenschritt verwendet, damit die Prozessersetzung verwendet werden kann,
tail
um die erste Zeile für uns zu überspringen, damit wir nicht in einer Endlosschleife enden. Einige Interpreter verlangen, dass die Datei durchsuchbar ist, und sie akzeptieren eine solche Pipeline nicht.Es lohnt sich zu überlegen, ob Sie das wirklich tun möchten. Abgesehen von Sicherheitsbedenken ist es einfach nicht sehr nützlich: Bei wenigen Skripten können die Interpreten so geändert werden, und wo sie können, wären Sie mit ziemlicher Sicherheit besser dran mit einer eingeschränkteren Logik, die die richtige für die Situation hervorgebracht hat (Vielleicht ein Shell-Skript dazwischen, das den Interpreter mit dem Pfad zum realen Skript als Argument aufruft).
* Nicht immer; Unter bestimmten Umständen lesen einige Shells es selbst, aber sie führen keine variable Erweiterung durch.
quelle
#!
Zeile. Wennexecve
diesENOEXEC
aufgrund einer fehlenden#!
Zeile fehlschlägt, kann die Shell auf andere Weise entscheiden, welcher Interpreter verwendet werden soll. Auf diese sollte man sich jedoch nicht verlassen, da verschiedene Shells unterschiedliche Interpreter für dasselbe Skript auswählen können.Ich weiß nicht, ob dies der Anwendungsfall ist, an den Sie denken, aber eine Sache, die Sie tun können , ist
so dass Ihr Skript verwendet die erste
python
in$PATH
anstatt zu hart Code benötigen/usr/bin/python
, die nicht gut auf irgendeinem System funktionieren könnten , wo die „gute“ Version von Python in ist/usr/local/bin
oder/opt
oder was auch immer.Warum ist es besser, "#! / Usr / bin / env NAME" anstelle von "#! / Path / to / NAME" als Shebang zu verwenden?
Dadurch wird keine Endlosschleife erstellt, da der Python-Interpreter (der
env
die Datei aufruft) die#!
Zeile nur als Kommentar behandelt. Dies ist eine Art Punkt des#!
Entwurfs, da viele Sprachen#
als Kommentarzeichen verwendet werden.Um dies zu erweitern, können Sie ein Polyglot-Programm schreiben, das zunächst unter ausgeführt
#!/bin/sh
wird, dann aber herausfindet, welcher Interpreter tatsächlich verwendet werden soll, und dieses im selben Skript aufruft.Es stellt sich heraus, dass es bereits eine Webseite mit mehrzeiligen Shebang-Tricks für viele Sprachen gibt, auch für kompilierte Sprachen (das Skript gibt einen Teil von sich an einen Compiler weiter und führt die Ausgabe aus).
Die
perlrun
Manpage gibt dieses Beispiel als Alternative zu#!/usr/bin/env perl
:Wenn es als
/bin/sh
Skript ausgeführt wird, wird eseval
inperl -x -wS
Ihrem Skript ausgeführt und gibt Ihre Argumente weiter.Wenn Perl es ausführt,
eval
wird das von derif 0;
in der nächsten Zeile gesteuert , so dass es nie ausgeführt wird. Im Gegensatz dazush
werden Perl-Anweisungen nicht durch einen Zeilenumbruch beendet.Sie können dies komplexer gestalten, indem Sie
"$SHEBANG"
anstelle vonperl
oder sogar mehreresh
Befehle ausführen, um einen zu verwendenden Perl-Interpreter auszuwählen.quelle
Ich denke, das ist was du willst:
Erläuterung:
Verwenden Sie
\$shell_var
file act als "Variable", um die gewünschte Shell zu definieren.readlink "/proc/$$/exe"
druckt die aktuelle Shell .Da dash keine
function f { echo hello world; }
Syntax unterstützt , wurde ein Fehler erzeugtfunction: not found
, aber wenn Sie die Shell in bash in\$shell_var
file ändern, tritt kein Fehler mehr auf.Der vollständige Dateipfad (oder der relative Pfad, wenn ./hole.sh in / tmp ausgeführt wird) wird
$@
an die\$shell_var
Datei übergeben und/tmp/hole.sh
im Inneren ausgeführt\$shell_var
.quelle