569 Stimmen

Kann ein Shell-Skript Umgebungsvariablen der aufrufenden Shell setzen?

Ich versuche, ein Shell-Skript zu schreiben, das, wenn es ausgeführt wird, einige Umgebungsvariablen setzt, die in der Shell des Aufrufers gesetzt bleiben.

setenv FOO foo

in csh/tcsh, oder

export FOO=foo

in sh/bash nur während der Ausführung des Skripts setzen.

Ich weiß bereits, dass

source myscript

führt die Befehle des Skripts aus, anstatt eine neue Shell zu starten, und das kann dazu führen, dass die Umgebung des "Aufrufers" festgelegt wird.

Aber hier ist der Haken:

Ich möchte, dass dieses Skript entweder von bash oder csh aus aufgerufen werden kann. Mit anderen Worten, ich möchte, dass Benutzer einer der beiden Shells mein Skript ausführen können und dass sich die Umgebung ihrer Shells ändert. Source" wird also nicht funktionieren, da ein Benutzer, der csh ausführt, kein Bash-Skript aufrufen kann und ein Benutzer, der bash ausführt, kein csh-Skript aufrufen kann.

Gibt es eine vernünftige Lösung, bei der man nicht ZWEI Versionen des Skripts schreiben und pflegen muss?

2voto

user1802263 Punkte 73

Es ist nicht das, was ich als herausragend bezeichnen würde, aber das funktioniert auch, wenn Sie das Skript ohnehin von der Shell aus aufrufen müssen. Es ist keine gute Lösung, aber für eine einzelne statische Umgebungsvariable funktioniert es gut genug.

1.) Erstellen Sie ein Skript mit einer Bedingung, die entweder 0 (erfolgreich) oder 1 (nicht erfolgreich) auslöst.

if [[ $foo == "True" ]]; then
    exit 0
else
    exit 1

2.) Erstellen Sie einen Alias, der vom Exit-Code abhängig ist.

alias='myscript.sh && export MyVariable'

Sie rufen den Alias auf, der das Skript aufruft, das die Bedingung auswertet, die erforderlich ist, um über das '&&' die Null zu verlassen, um die Umgebungsvariable in der übergeordneten Shell zu setzen.

Das ist zwar Treibgut, kann aber in einer Notlage nützlich sein.

1voto

David Lovering Punkte 11

Technisch gesehen ist das korrekt, nur dass 'eval' keine andere Shell aufspaltet. Aus der Sicht der Anwendung, die Sie in der geänderten Umgebung ausführen wollen, ist der Unterschied jedoch gleich Null: Das Kind erbt die Umgebung des Elternteils, so dass die (geänderte) Umgebung an alle nachgeordneten Prozesse weitergegeben wird.

Ipso facto bleibt die geänderte Umgebungsvariable erhalten, solange Sie unter dem übergeordneten Programm/Shell laufen.

Wenn es absolut notwendig ist, dass die Umgebungsvariable bestehen bleibt, nachdem die übergeordnete Shell (Perl oder Shell) beendet wurde, muss die übergeordnete Shell die schwere Arbeit übernehmen. Eine Methode, die ich in der Dokumentation gesehen habe, besteht darin, dass das aktuelle Skript eine ausführbare Datei mit der notwendigen "Export"-Sprache erzeugt und dann die übergeordnete Shell dazu bringt, sie auszuführen - wobei man sich immer der Tatsache bewusst sein muss, dass man dem Befehl "source" voranstellen muss, wenn man versucht, eine nichtflüchtige Version der geänderten Umgebung zu hinterlassen. Bestenfalls eine Kluge.

Die zweite Methode besteht darin, das Skript, das die Shell-Umgebung initiiert (.bashrc oder was auch immer), so zu ändern, dass es den geänderten Parameter enthält. Dies kann gefährlich sein - wenn Sie das Initialisierungsskript vermasseln, kann es dazu führen, dass Ihre Shell beim nächsten Startversuch nicht mehr verfügbar ist. Es gibt viele Werkzeuge, um die aktuelle Shell zu modifizieren; indem Sie die notwendigen Änderungen am "Launcher" vornehmen, schieben Sie diese Änderungen auch nach vorne. Im Allgemeinen ist das keine gute Idee; wenn Sie die Umgebungsänderungen nur für ein bestimmtes Anwendungspaket benötigen, müssen Sie das Shell-Startskript anschließend wieder in seinen ursprünglichen Zustand zurückversetzen (mit vi oder ähnlichem).

Kurz gesagt, es gibt keine guten (und einfachen) Methoden. Vermutlich wurde dies erschwert, um sicherzustellen, dass die Sicherheit des Systems nicht unwiderruflich beeinträchtigt wird.

1voto

Andrew Punkte 4161

Die kurze Antwort ist nein, Sie können die Umgebung des übergeordneten Prozesses nicht ändern, aber es scheint, dass Sie eine Umgebung mit benutzerdefinierten Umgebungsvariablen und der vom Benutzer gewählten Shell wünschen.

Warum also nicht einfach etwas wie

#!/usr/bin/env bash
FOO=foo $SHELL

Wenn Sie dann mit der Umgebung fertig sind, brauchen Sie nur exit .

1voto

user1667208 Punkte 29

Sie können auch Aliasnamen verwenden

alias your_env='source ~/scripts/your_env.sh'

1voto

Ich habe dies vor vielen Jahren getan. Wenn ich mich richtig erinnere, fügte ich in .bashrc und .cshrc jeweils einen Alias mit Parametern ein, der die jeweiligen Formen der Umgebungseinstellung auf eine gemeinsame Form zurückführte.

Dann hat das Skript, das Sie in einer der beiden Shells erstellen, einen Befehl mit dieser letzten Form, der in jeder Shell als Alias verwendet wird.

Wenn ich die konkreten Aliasnamen finde, werde ich sie veröffentlichen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X