Wo soll ich eine Umgebungsvariable exportieren, damit alle Kombinationen von Bash / Dash, Interaktiv / Nicht-Interaktiv, Anmelden / Nicht-Anmelden sie aufnehmen?


11

Hier ist die Motivation für die Frage:

Ich verwende Ubuntu 12.04 LTS 2 mit dem Unity-Desktop. In meiner .bashrc-Datei hänge ich mehrere Verzeichnisse an meine PATH-Variable an und definiere einige Umgebungsvariablen, z. B. JAVA_HOME. Wenn ich Anwendungen von einem Terminal aus starte (mit bash, meiner Standard-Shell), funktioniert dies hervorragend, aber für einige der Verknüpfungen, die den Unity-Launcher verwenden, werden Apps ausgeführt, die anscheinend für die Verwendung von #! / Bin / sh definiert sind ist auf / bin / dash ausgerichtet und nimmt den Inhalt von ~ / .bashrc oder ~ / .profile nicht auf.

Ich nehme an, ich könnte all diese Verknüpfungen ändern, um / bin / bash anstelle von / bin / sh zu verwenden, um zu erzwingen, dass die .bashrc-Änderungen übernommen werden, aber das scheint wirklich hackig zu sein.

Angesichts der Tatsache, dass Ubuntu 12.04 (standardmäßig) Aliase / bin / sh in / bin / dash ist und meine Standard-Shell / bin / bash ist, gibt es einen einzigen Ort, an dem ich den PATH ändern und Umgebungsvariablen definieren kann, wenn ich sie möchte unter all diesen Umständen anwesend sein :

  1. Immer wenn ich eine Bash-Shell ohne Login erstelle (mit dem Terminal in Unity)
  2. Immer wenn ich eine Login-Bash-Shell erstelle (z. B. Remote-Anmeldung über ssh)
  3. Immer wenn ich einen Unity-Anwendungsstarter verwende (vorausgesetzt, der Starter verwendet / bin / sh).
  4. Immer wenn ein Cron-Job ausgeführt wird (vorausgesetzt, SHELL = / bin / sh in / etc / crontab).

Wenn ich richtig verstehe, vermute ich das:

  • (1) / (2) und (3) / (4) sind unterschiedlich, weil (1) / (2) Bash und (3) / (4) Bindestrich sind.
  • (1) und (2) unterscheiden sich, da die Dateien, die bash zum Laden auswählt, unterschiedlich sind, je nachdem, ob es sich um eine Anmeldeshell handelt oder nicht.
  • (3) und (4) sind unterschiedlich, da (3) irgendwann nach dem Anmelden eintrifft (und daher ~ / .profile von einem seiner übergeordneten Prozesse bezogen wurde, während (4) irgendwann eintritt Punkt, an dem ich nicht angemeldet bin und daher ~ / .profile nicht gelesen wurde.

(Ich wäre nicht überrascht, wenn auch andere Faktoren eine Rolle spielen würden, z. B. ob die Shell interaktiv ist oder nicht. Daher gibt es wahrscheinlich mehr Kombinationen, mit denen ich nicht einmal gerechnet habe ... Ich bin froh, dass meine Frage "verbessert" wurde " In diesem Fall.)

Ich würde erwarten, dass irgendwann jemand eine Art Leitfaden erstellt hat, der Ihnen sagt, wie / wo Umgebungsvariablen auf eine Shell-unabhängige Weise (oder zumindest auf eine Dash / Bash-kompatible Weise) geändert werden können ... Ich kann es einfach. ' Es scheint nicht die richtigen Suchbegriffe zu finden, um einen solchen Leitfaden zu finden.

Lösungen oder Hinweise auf Lösungen sehr geschätzt!

Aktualisiert:

  • Erläuterung: Dies ist der Standard-Ubuntu-Benutzer, der durch den 12.04-Installationsprozess erstellt wurde. Es hat ein ~ / .profile (das explizit ~ / .bashrc angibt), und die einzigen vorhandenen ~ / .bash * -Dateien sind .bashrc, .bash_history und .bash_logout ... also nein, es gibt kein .bash_profile.
  • Schwerpunkt auf -umfang: Ich weiß nicht wirklich über alle Shells anders als der Standard interaktiv Shell (bash) und jeden Skript kümmern , die (aliased zu Bindestrich) zu verwenden / ist / sh geschieht, so gibt es keine Notwendigkeit , diese mit etwas zu erschweren zusätzlich für tcsh / ksh / zsh / etc. Unterstützung.

2
Platzieren Sie es in einer Datei und lassen Sie es von anderen RC-Dateien als Quelle verwenden.
konsolebox

Laut der Dash-Manpage, die ich hier habe, sollte es $ HOME / .profile für Login-Shells lauten.
Etan Reisner

@konsolebox Welche RC-Dateien? AFAICT, Dash hat keine RC-Datei. Und wie gesagt, Dash scheint den Inhalt von ~ / .profile nicht aufzunehmen.

@EtanReisner Ja, und das ist der Punkt der Frage. Wenn dash nicht als Login-Shell ausgeführt wird (und daher ~ / .profile nicht bezogen wird), was dann?

@ Mickalot Laufen Sie Dash interaktiv? Wenn nicht, versuchen Sie, die Option -l hinzuzufügen.
konsolebox

Antworten:


9

Der Shell-Aufruf ist etwas kompliziert. Die Bash- und Dash-Manpages enthalten INVOCATIONAbschnitte dazu.

Zusammenfassend heißt es (es gibt mehr Details in der Manpage, Sie sollten es lesen):

When bash is                   | it reads
-------------------------------|----------
login shell                    | /etc/profile and then the first of ~/.bash_profile, ~/.bash_login or ~/.profile that exists.
                               |
interactive non-login shell    | /etc/bash.bashrc then ~/.bashrc
                               |
non-interactive shell          | The contents of $BASH_ENV (if it exists)
                               |
interactive (as "sh")          | The contents of $ENV (if it exists)

- -

When dash is                   | it reads
-------------------------------|---------
login shell                    | /etc/profile then .profile
                               |
interactive shell              | The contents of ENV (it it exists, can be set in .profile as well as in initial environment)

Ich weiß nicht ohne weiteres von anderen Muscheln, da ich keine von ihnen benutze. Am besten legen Sie einige Umgebungsvariablen so fest, dass sie auf das allgemeine Standortskript verweisen, und geben diese (falls zutreffend) in einigen Fällen, die nicht behandelt werden, manuell an.


Leider ist der Kern dieses Problems derjenige, der in Ihrem Dash-Tisch fehlt. Wenn der Unity-Desktop ein Skript aufruft, das mit #! / Bin / sh beginnt, wird (ich nehme an) eine nicht angemeldete, nicht interaktive Dash-Shell gestartet. Die Frage ist also: Wie kann ich die gleichen Umgebungsvariablen zur Verfügung gibt , die überall in der Matrix vorhanden ist?

Recht. Ich kann mir vorstellen, dass bash deshalb BASH_ENV für diesen Slot hinzugefügt hat. Angesichts der Tatsache, dass Dash anscheinend nichts in diesem Slot funktioniert, bin ich mir nicht sicher, ob Sie dieses Problem lösen können, ohne die Änderung in der Umgebung der Anwendung zu beeinflussen, die Dash startet (so dass Dash es erbt). Dies würde erfordern, dass die Umgebungsvariablen in Ihrer X-Umgebung festgelegt werden. Hier kommt der Kommentar .xsession (rc) von @Mickalot ins Spiel. Dies lässt, wie er angedeutet hat, Punkt vier immer noch weg (aber ich glaube, das ist eigentlich etwas beabsichtigt).
Etan Reisner

Da ich auf Ubuntu 12.04 LTS bin, ist cron eigentlich pixie-cron, also kann ich env-Variablen in meiner crontab-Datei definieren ... Ich vermute, SHELL = / bin / bash und BASH_ENV = ~ / .bashrc sollten es tun?

3

Es gibt also mehrere Möglichkeiten, dies zu erreichen. Viele Leute werden entweder:

ein. Haben Sie eine Datei, die allen Ihren Sh-Shells gemeinsam ist, sagen Sie, .shcommonund geben Sie diese in jedem .profile .bashrc .kshrcEt cetra einfach mit ein. .shcommon

b. Fügen Sie alles ein .profileund beziehen Sie dies aus den anderen Dateien.

Dinge, die für bestimmte Shells oder für interaktive oder nicht interaktive Shells benötigt werden, können dann vor dem Sourcing in die entsprechende Datei gestellt werden .shcommon

Persönlich mag ich es nicht, mehrere Dateien zu verwalten. Also benutze ich den folgenden Ansatz:

Zuerst geht alles rein, was ich brauche. .profile Da ich einige Bash- und Ksh-spezifische Dinge habe, bestimme ich den aktuellen Shell-Namen wie folgt:

# get name of current shell
# strip leading - from login shell
export SHELLNAME="${0#-}"

und dann Befehle für bestimmte Shells in etwa der folgenden Form haben (einige würden eine case-Anweisung bevorzugen).

if [ "$SHELLNAME" = 'bash' ]
then
    shopt -s checkwinsize

elif [ "$SHELLNAME" = 'ksh' ]
then
    stty erase ^?
fi

Wenn ich Befehle habe, die nur in interaktiven Shells ausgeführt werden sollen, verwende ich Folgendes:

# check for interactive flag i in shell options $-
# in bash and ksh you could use the following, but breaks in dash
# if [[ $- == *i* ]]
if [ "$(echo $- | grep i)" != "" ]
then
  fortune
fi

Dinge, die in allen Sh-Shells üblich sind, z. B. PATHkönnen ganz oben stehen.

Dann verwende ich Symlinks, um dieselbe Datei in alle Sh-Shells zu laden:

ln -s .profile .bashrc
ln -s .profile .kshrc

Ein paar Randnotizen, wenn Sie eine haben .bash_profile, dann wird bash diese laden, .profileaber dash und ksh werden immer noch geladen. .profile Dies kann Teil Ihres Problems sein.

Möglicherweise möchten Sie auch die Verwendung #!/bin/bashin Ihren Skripten in Betracht ziehen, anstatt #!/bin/dashwirklich POSIX-kompatible Skripte zu verwenden. bash hat viele zusätzliche Funktionen, die sehr nett sind und Dash oder Bash aufgerufen werden, da sh viele dieser Funktionen deaktiviert.

Auf der Bash-Manpage wird außerdem gut erklärt, wann .profileVersus .bashrcgeladen wird. Ähnliche Regeln gelten für ksh. Mit Dash wird .profilebeim Anmelden geladen und Sie können beim Start interaktiver Shells eine Datei laden, die mithilfe der ENVUmgebungsvariablen in angegeben wird .profile(überprüfen Sie auch die Dash-Manpage und suchen Sie nach .profile).


Könnten Sie nicht einfach $ 0 auf den Shell-Namen testen? Gibt es Muscheln / Fälle, in denen das nicht funktioniert?
Etan Reisner

Ebenso reicht die Überprüfung auf i in $ - für den interaktiven Shell-Test nicht aus? (Es wird auf interaktiven Shells ohne einen von mir gewährten tty ausgelöst, aber das kann eine unerwünschte Nebenwirkung sein oder auch nicht.)
Etan Reisner

@Etan: Hrm, ich weiß, dass ich es zuerst versucht habe $0und auf Probleme gestoßen bin ... Ich kann mich anscheinend nicht genau erinnern, was sie waren. Die direkte Anmeldung an der Konsole wird zwar $0als -bashstatt bashangezeigt, dies könnte jedoch behoben werden.

@ Etan: Ja, das Einchecken nach i in $-würde auch funktionieren. Ich müsste darüber nachdenken, wann Sie eine interaktive Shell ohne tty haben würden. Ihre Lösung hat aus irgendeinem Grund ein besseres "Gefühl", das kann ich ändern.

Das -in -bashbedeutet "Login-Shell", aber ja, Sie müssten dies an Stellen berücksichtigen, an denen Sie den Wert testen oder ihn jemandem anzeigen möchten.
Etan Reisner

0

Da die Fälle (1) und (2) durch die Beschaffung meiner Umgebungsvariablen in .bashrc und .profile gelöst werden, lautet die eigentliche Frage: "Wie heißt die Datei, aus der ich dieselben Variablen für (3) und (4) beziehe?"

Es sieht so aus, als gäbe es eine Antwort auf Teil (3) der Frage (wie bekomme ich die Umgebungsvariable, die in den Unity-Desktop importiert werden soll) auf askubuntu . Dort wird vorgeschlagen, eine ~ / .xsessionrc-Datei zu erstellen, die von / etc / X11 / Xsession bezogen wird. (Ich habe das ausprobiert und es scheint zu funktionieren ... yay!)

Ich bin immer noch ratlos darüber, was ich tun soll (4). Wenn ich einen Cron-Job (oder Daemon) erstelle, kann ich '/ bin / foo' durch 'bash -i -c / bin / foo' ersetzen, um ihn zu zwingen, bash zum Laden der richtigen Umgebungsvariablen zu verwenden, aber Dies bedeutet auch, dass ich an Tools von Drittanbietern basteln muss, die möglicherweise Daemon-Aufgaben oder Cron-Jobs in meinem Namen installieren. Yuk.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.