logo hsb.horse
← Zur Blog-Übersicht

Blog

Verhalten von sh -c und Regeln zum Lesen von zsh-Konfigurationsdateien

Organisiert das Verhalten des Befehls sh -c, die Vererbungsregeln von Umgebungsvariablen, die Gültigkeit von Shebang und wie zsh-Konfigurationsdateien (.zshrc, .zshenv usw.) gelesen werden, wenn Skripte ausgeführt werden.

Veröffentlicht:

Wir werden den Befehl sh -c und das Verhalten beim Aufruf eines Skripts daraus organisieren, insbesondere wie die Konfigurationsdateien rund um zsh (.zshrc usw.) gelesen werden.

Dies ist der Punkt, an dem Sie leicht von Docker-Einstiegspunkten, CI/CD-Einstellungen und Aufrufen externer Tools begeistert sein können.

Was ist sh -c?

Kurz gesagt, es „interpretiert die Argumentzeichenfolge als Befehl und führt ihn aus“.

Terminal window
sh -c "echo Hello World"

Ich spreche davon, wie es sich von der normalen Eingabe eines Befehls unterscheidet, aber es wird hauptsächlich in den folgenden Szenen benötigt.

Wenn Sie mit sudo umleiten möchten

sudo echo "text" > /etc/file führt zu einem Berechtigungsfehler. Dies liegt daran, dass die Umleitung mit allgemeinen Benutzerrechten durchgeführt wird.

sudo sh -c "echo 'text' > /etc/file" ist erfolgreich, da die gesamte Shell als Root ausgeführt wird.

Wenn Sie && oder | mit Docker/K8s verwenden möchten

Wenn Sie mehrere Befehle verbinden oder eine Pipe mit CMD oder ENTRYPOINT verwenden möchten, wird die Syntax nicht analysiert, es sei denn, Sie gehen durch die Shell.

Wenn Sie Go-Binärdateien usw. über sh ausführen möchten

sh ./my-binary verursacht einen Fehler, weil es „versucht, die Binärdatei als Shell-Skript zu lesen“.

sh -c ./my-binary sagt „Führen Sie den Befehl in diesem Pfad aus“, sodass er auch im Binärformat ausgeführt werden kann.

Vererbungsregeln für Umgebungsvariablen

Werden Umgebungsvariablen an das mit sh -c aufgerufene Skript übergeben?

Bestätigungscode

Terminal window
# 親側
export MY_ENV="hoge"
sh -c "./sample.sh"
sample.sh
echo "$MY_ENV"

Ergebnisse

  • Cover, wenn exportiert (hoge erscheint)
  • Wird nicht bestanden, wenn nicht exportiert (wird leer sein)

Die Variable export wird vom untergeordneten Prozess (sh -c) an den untergeordneten Prozess (sample.sh) vererbt. Natürlich müssen Sie sich darüber im Klaren sein, dass sh -c einen separaten Prozess startet.

Ist Shebang wirksam?

Beim Aufruf des Skripts für zsh von main.sh über sh -c.

main.sh```sh sh -c ”./sample.sh”

**sample.sh**```sh
#!/usr/bin/env zsh
# zsh特有の処理...

Ergebnisse

**Es funktioniert ordnungsgemäß als zsh. **

sh fungiert einfach als Launcher, und das Betriebssystem schaut sich die erste Zeile (Shebang) von sample.sh an und startet zsh.

Beim Lesen mit Quelle (oder .) ist es jedoch NG.

  • sh -c "./sample.sh" → zsh startet und läuft (Shebang aktiviert)
  • sh -c ". ./sample.sh" → Geladen als sh (Shebang ignoriert = Syntaxfehler)

Wird die zsh-Konfigurationsdatei gelesen?

Werden .zshrc und .zprofile geladen, wenn sample.sh (zsh-Skript) ausgeführt wird?

Fazit: Kaum belastet

DateinameGeladen?Grund
.zshenvJANur lesen. Gültig in allen Modi.
.zprofileNEINWird ignoriert, da es sich nicht um eine „Login-Shell“ handelt.
.zshrcNEIN**Ignoriert, da es sich nicht um eine „interaktive Shell“ handelt. **
.zloginNEINWird ignoriert, da es sich nicht um eine „Login-Shell“ handelt.

Beim Ausführen eines Skripts (nicht interaktiver Modus) wird .zshrc übersprungen, um unnötige Ausgaben oder Aliase zu vermeiden.

Aus diesem Grund funktioniert der in .zshrc geschriebene Alias ​​im Skript nicht.

Wenn Sie es wirklich laden möchten

Die einzige Möglichkeit besteht darin, im Skript explizit source anzugeben.

#!/usr/bin/env zsh
source ~/.zshrc # 無理やり読み込む
my_alias_command

Wenn .zshrc jedoch Ausgaben wie Echo enthält, wird diese mit der Skriptausgabe vermischt, daher wird dies nicht empfohlen.

Die richtige Antwort besteht darin, die vom Skript benötigten Umgebungsvariablen in .zshenv zu schreiben (unabhängig davon, ob sie gut oder schlecht sind).

Zusammenfassung

sh -c ist praktisch, kann aber verwirrend werden, wenn Sie Prozessgrenzen und Regeln zum Laden von Konfigurationsdateien nicht verstehen.

Insbesondere in Docker- und CI/CD-Umgebungen funktioniert es möglicherweise nicht innerhalb des Containers, selbst wenn es lokal funktioniert. Dies wird häufig dadurch verursacht, dass die Umgebungsvariable export vergessen wird oder von .zshrc abhängig ist.

Es ist sicher, in Skripten verwendete Einstellungen in .zshenv zu konsolidieren und Funktionen und Skripte anstelle von Aliasen zu verwenden.