Was ist der beste Weg, um Shell-Skripte zu verteilen, wenn das Verhalten von Shells durch geändert werden kann set
und daher unvorhersehbar ist?
Wird beispielsweise rm *.txt
in den Umgebungen, in denen es ausgeführt wurde , nicht wie erwartet set -f
ausgeführt. Wie soll ich sicherstellen, dass rm *.txt
in allen Umgebungen alle Textdateien in einem aktuellen Verzeichnis entfernt werden?
Wie kann ich sicherstellen, dass Shell-Skripte wie erwartet ausgeführt werden, bevor sie allgemein verteilt werden?
bash
shell
shell-script
hoge
quelle
quelle
shell_state=$(set +o)
... Skript ...eval "$shell_state"
#!
um anzugeben, welche Shell-Optionen Sie möchten.Antworten:
Shell-Skripte werden normalerweise so behandelt, als wären sie mit jeder anderen Art von ausführbarer Datei identisch, z. B. Binärdateien, Python-Skripten, Perl-Skripten oder anderen Skripten. Sie haben oben einen Shebang , der den Kernel anweist, sie durch die Shell auszuführen. Es wird erwartet, dass sie wie jeder andere Befehl aufgerufen werden.
Daher wird bei jedem Aufruf des Skripts eine neue Shell gestartet, und Einstellungen, wie
set -f
sie in der aufrufenden Shell oder in einer anderen Shell-Instanz im System vorhanden sind, sind irrelevant.Natürlich können Benutzer Ihr Skript als Quelle ausführen, anstatt es auszuführen, zum Beispiel wie folgt:
oder um es in einer Shell auszuführen, die nicht standardmäßige Einstellungen wie diese hat:
Dies wird jedoch nicht als normale Methode oder als Aufruf Ihres Skripts angesehen, und Benutzer, die dies tun, sollten erwarten, was auch immer sie als Ergebnis erhalten.
Beachten Sie, dass es einige Skripte gibt, die beschafft und nicht ausgeführt werden sollen, da sie beispielsweise dazu dienen, das cwd zu ändern oder Umgebungsvariablen festzulegen, die in der Umgebung der Sourcing-Shell berücksichtigt werden müssen. Diese Skripte sind jedoch in der Minderheit und es wird normalerweise als Teil eines vereinbarten Protokolls durchgeführt. Diese Dateien können eher als "Plugins" für jedes System betrachtet werden, von dem sie erwartet werden, und nicht als unabhängige Skripte. Beispielsweise werden Dateien
/etc/rc*.d
mit Namen, die auf enden,.sh
vom Startskript-Subsystem bezogen und nicht ausgeführt. Es wird dokumentiert, dass dies der Fall ist, wenn Sie eine Datei mit einem solchen Namen in platzieren/etc/rc*.d
und wenn es fertig ist, ist es absichtlich gemacht. Die Konvention, Dateien zu benennen, die beschafft und nicht auf diese Weise ausgeführt werden sollen, wird auch an anderer Stelle befolgt, jedoch nicht allgemein.Es ist richtig, dass Dateien, die auf diese Weise bezogen werden sollen, darauf achten müssen, welche Einstellungen in der Umgebung ihres Anrufers vorhanden sein können, die sich auf das Verhalten der Shell auswirken können. Dann sollte das vereinbarte Protokoll jedoch idealerweise eine vorhersehbare Ausführungsumgebung versprechen.
quelle
zsh
verfügt über eine Funktion, mit der die Optionen in einem Know-Set in einem lokalen Kontext (emulate -L zsh
) wiederhergestellt werden können, das in allen mit zsh gelieferten und als zsh-Code geschriebenen Erweiterungen häufig verwendet wird. Sehen Sie, wie das Bash-Vervollständigungssystem kläglich ausfällt, wenn Sie einige Optionen wie zfailglob
.#! /bin/csh -f
statt#! /bin/csh
zum Beispiel.zshenv
. Pass auf, was duzshenv
aus diesem Grund eingegeben hast !emulate -L
in diesem Fall) nicht wusste, indem du eine meiner Antworten kommentierst, und ich weiß das zu schätzen.~/.zshenv
(wo Sie Einstellungen (im Allgemeinen env vars) für alle zshs (interaktiv oder nicht) erzwingen möchten, die unter Ihrem Namen aufgerufen werden und im Allgemeinen nicht verwendet werden, außer um ein anderes Nicht-zsh-Problem zu umgehen) ist getrennt von~/.zshrc
(interaktiv) Anpassungsshell), also ist es eine Funktion, kein Fehler. (Sie können zsh -f verwenden) Ein Fehler ist, wenn einige nicht interaktive Bash-Shells Ihre lesen~/.bashrc
(wie über ssh und Sie müssen Code hinzufügen, um sich davor zu schützen) oder wenn eine interaktive Bash (die Login-Shells) sie nicht lesen (und wieder müssen Sie Code hinzufügen, um das Problem zu umgehen~/.bash_profile
).