Umgebungsvariablen in bash_profile oder bashrc?

36

Ich habe diese Frage [Blog] gefunden: Der Unterschied zwischen .bashrc und .bash_profile ist sehr nützlich, aber nachdem ich die meistgewählte Antwort gesehen habe (übrigens sehr gut), habe ich weitere Fragen. Gegen Ende der am häufigsten gewählten, richtigen Antwort sehe ich die Aussage wie folgt:

Beachten Sie, dass hier und da möglicherweise Empfehlungen angezeigt werden, entweder Definitionen von Umgebungsvariablen in ~ / .bashrc aufzunehmen oder Anmelde-Shells immer in Terminals zu starten. Beides sind schlechte Ideen.

  1. Warum ist es eine schlechte Idee (ich versuche nicht zu kämpfen, ich will nur verstehen)?

  2. Wenn ich eine Umgebungsvariable festlegen und sie dem PATH hinzufügen möchte (zum Beispiel JAVA_HOME), wo wäre es der beste Ort, um den Exporteintrag abzulegen? in ~ / .bash_profile oder ~ / .bashrc ?

  3. Wenn die Antwort auf Frage 2 ~ / .bash_profile lautet , habe ich zwei weitere Fragen:

    3.1. Was würdest du unter ~ / .bashrc stellen ? nur Aliase?

    3.2. In einer Shell ohne Login glaube ich, dass das ~ / .bash_profile nicht "abgeholt" wird. Wenn der Export von JAVA_HOME Eintrag in bash_profile ist , würde ich in der Lage sein , auszuführen Javac & Java - Befehle? Würde es sie auf dem PFAD finden? Ist das der Grund, warum einige Posts und Foren vorschlagen, JAVA_HOME und dergleichen auf ~ / .bashrc zu setzen ?

    Danke im Voraus.

Viriato
quelle

Antworten:

26

In einem modernen System ist es nicht besonders üblich, auf Fälle zu stoßen, in denen es wichtig ist, aber es passiert. (Insbesondere, wenn Sie Shell-Operationen vimwie :r !commandoder in Inline- !<motion>commandForm verwenden.)

Was würdest du unter ~ / .bashrc stellen? nur Aliase?

Sie ~/.bashrcfügen Dinge hinzu , die Subshells nicht automatisch erben würden. Dies bedeutet meistens Aliase und Funktionen, obwohl Sie manchmal variable Einstellungen haben, die außerhalb der Shell nicht sichtbar sein sollen (dies ist sehr selten). Man könnte argumentieren, dass diese irgendwie exportiert werden sollten, aber verschiedene experimentelle Versuche führten zu Kompatibilitätsproblemen beim Versuch, sie in der Umgebung zu verstecken, und wurden größtenteils aufgegeben.

Wenn ich eine Umgebungsvariable festlegen und sie dem PATH hinzufügen möchte (zum Beispiel JAVA_HOME), wo wäre es der beste Ort, um den Exporteintrag abzulegen? in ~ / .bash_profile oder ~ / .bashrc?

Sie legen die Umgebungseinstellungen ~/.bash_profileso fest, dass sie die richtigen Anfangseinstellungen erhalten. Manchmal möchten Sie diese überschreiben (häufig wird dies von komplexen Umgebungen wie Matlab oder Cadence durchgeführt). Wenn Sie ~/.bashrcdie Umgebungseinstellungen übernehmen, gehen die Anpassungen der Umgebungen verloren, wenn Shells in diesen Umgebungen ausgeführt werden. Infolgedessen funktionieren die Dinge möglicherweise nicht richtig. Dies gilt auch, wenn Sie ein Paket wie Module , virtualenv , rvm usw. verwenden, um mehrere Entwicklungsumgebungen zu verwalten. Wenn Sie Ihre Einstellungen vornehmen ~/.bashrc, können Sie die gewünschte Umgebung nicht in Ihrem Editor ausführen, sondern werden auf die Systemstandardeinstellungen zurückgesetzt.

In einer Shell ohne Login glaube ich, dass das ~ / .bash_profile nicht "abgeholt" wird.

Das ist richtig; Normalerweise soll die anfängliche Shell eine Anmeldeshell sein und alle unter dieser Shell gestarteten Shells dürfen keine Anmeldeshells sein. Wenn die anfängliche Shell keine Anmeldeshell ist, haben Sie keine Standardeinstellungen PATHoder verschiedene andere Einstellungen (einschließlich Ihres JAVA_HOMEBeispiels).

Die meisten Desktop-Umgebungen, die von Display-Managern gestartet werden (d. H. Die meisten grafischen Anmeldungen), richten keine Anmeldeumgebung für den gesamten Desktop ein, sodass Sie die anfängliche Shell in Terminals als Anmelde-Shell ausführen müssen. Dies führt zu einer Reihe von Problemen (insbesondere, dass die PATHfür Programme verfügbaren Programme, die von z. B. Panels ausgeführt werden, nicht ordnungsgemäß eingerichtet sind, da das Panel kein Terminal ist und nicht ausgeführt wurde ~/.bash_profile), stellt jedoch einen vernünftigen Kompromiss dar, da dies nicht immer möglich ist Sicheres Ausführen ~/.bash_profilein der nicht interaktiven Umgebung zu Beginn einer Sitzung, die von einem Display-Manager gestartet wurde, je nach Inhalt. Es wird manchmal empfohlen, Umgebungseinstellungen in zu platzieren~/.bashrcanstatt stattdessen eine Login-Shell zu konfigurieren; Wie oben erläutert, funktioniert dies so lange, wie Sie diese Umgebung nicht überschreiben müssen, und es kommt zu ungewöhnlichen Brüchen, wenn Sie dies tun müssen.

Ich half vor kurzem ein Problem wie dieses auf OS X zu diagnostizieren , wo ein Benutzer, der in platziert Einstellungen hatte ~/.bashrcdann später begann mit rvmund perlbrew Säge merkwürdiges Verhalten, weil die Umgebungen durch die beiden waren „undone“ von eingerichtet ~/.bashrcinnen Editoren und sudo(die auf OS X Im Gegensatz zu Linux wird der Benutzer $HOMEso weitergegeben, dass er ~/.bashrcvon der Root-Shell ausgeführt wurde. Vor dem Versuch, diese Umgebungen zu verwenden, gab es kein Problem. Als sie anfingen, sie zu benutzen, waren sie verwirrt über den unerwarteten Verlust ihrer Einstellungen.

Geekosaurier
quelle
1
Ich denke, ich verstehe, ich muss es vielleicht mehrmals lesen, um es mehr zu verinnerlichen, aber ich schließe daraus Folgendes. In Unternehmensumgebungen empfiehlt es sich, Umgebungsvariablen in ~ / .bash_profile einzufügen, um eine genauere Kontrolle über die angepassten Shells zu erhalten, ohne dass die globalen Nebenwirkungen auftreten . In einer persönlichen Umgebung wie Ubuntu oder Linux Mint sollte ich es unter ~ / .bashrc (oder sogar in / etc / profile ) einstellen, um den PATH richtig einzustellen . Hab ich recht?
Viriato
Es hat weniger mit Unternehmensumgebungen zu tun als damit, ob Sie nur ein Benutzer oder ein Entwickler sind. Die Systeme mögen modulesund rvmsind Entwicklerwerkzeuge, ebenso wie Matlab und Cadence für etwas andere Definitionen von "Entwickler". Einfache Entwicklung erfordert auch sich nicht, aber wenn Sie zu Test gegen mehrere Versionen von Ruby benötigen, Perl oder Python dann wollen Sie wirklich so etwas wie rvm, perlbrewund virtualenv(jeweils) um zu helfen , halten sie alle gerade.
Geekosaurier
2

Um ehrlich zu sein, gibt es heutzutage kaum einen Unterschied, trotz dessen, was der Guru zu sagen hatte.

Das Problem dabei ist, dass wir uns heutzutage eher grafisch anmelden als über eine Anmeldeshell. In der Vergangenheit möchten wir Unix-Benutzer sofort nach der Anmeldung einen kurzen Bericht darüber sehen, was auf einem Server vor sich geht. Dann starten wir X über die Befehlszeile. Die Erstellung dieses Berichts dauert häufig einige Zeit (z. B. 10 bis 20 Sekunden). und dann wollen wir nicht dasselbe sehen, wenn wir zB xterm starten. also der unterschied.

Heutzutage denke ich nicht, dass die Unterscheidung jetzt wichtig ist. Ich denke, heutzutage, wenn Sie bashrc in bash_profile beziehen, kann Ihnen niemand die Schuld geben.

Beachten Sie, dass dies nicht für MacOS X gilt (jede gestartete terminal.app ist eine Login-Shell).

bubu
quelle
Ich bin mir nicht ganz sicher, ob ich alles richtig verstanden habe, aber wenn ich mich über ssh anmelde, das ist eine Login-Shell, werden bash_profile und bashrc bezogen, also ist es in diesem Fall vermutlich egal. Aber wenn ich mich grafisch anmelde (was bedeutet das)? Möchtest du dich in mein persönliches Ubuntu einloggen?
Viriato
Stimmen Sie mit der @bubu-Antwort hier überein - jedes Setup, bei dem ~/.bash_profilekeine Quelle vorhanden ~/.bashrcist, ist ziemlich schwer zu bearbeiten und grenzt an einen Defekt. Grafische Terminal-Apps bedeuten, dass es einfacher ist, einfach ~ / .bashrc zu beziehen und die gesamte Konfiguration dort abzulegen.
RichVel
1

Nun, bei "Grafischen Logins" kommt es darauf an, welche * DM Sie verwenden ...

Mit GDM (Gnome 3.18) habe ich folgendes:

/ etc / gdm / Xsession

#!/bin/sh   <= *important*

...

# First read /etc/profile and .profile
test -f /etc/profile && . /etc/profile
test -f "$HOME/.profile" && . "$HOME/.profile"
# Second read /etc/xprofile and .xprofile for X specific setup
test -f /etc/xprofile && . /etc/xprofile
test -f "$HOME/.xprofile" && . "$HOME/.xprofile"

Also wird ~ / .profile in login mit / bin / sh und nicht mit / bin / bash bezogen

Es gibt zwei Fälle

  1. / bin / sh ist mit / bin / bash verknüpft, wird jedoch im "POSIX / Bourne" -Modus ausgeführt
  2. / bin / sh ist / bin / dash (debian / ubuntu). Am schnellsten, aber mit weniger Funktionen (ShellShock-Unterstützung;) )

Das / bin / sh-Profil ist also ~ / .profile und nicht ~ / .bash_profile, ~ / .zprofile

Diese Datei sollte für "Shell Agnostic" -Einstellungen wie Pfad- und Umgebungsvariablen verwendet werden.

KEIN ausführbares Programm für die Nur-Login-Benutzerinteraktion sollte aber hier sein (Mailcheck, Fortune, etc ...)

Die ~ / .* rc sind nur für "interaktive" Sitzungen gedacht (zum Beispiel Aliase ...)

Bei interaktiven Login- Shells gibt es einen Unterschied zwischen bash und zsh

Bash-Quellen nur .bash_profile, während Zsh-Quellen in der Reihenfolge:

  1. ~ / .zprofile
  2. ~ / .zshrc
  3. ~ / zlogin (hier sind in ~ / .zshrc definierte Aliase verfügbar. Bei "interaktiven" + "Login" - Shells

Die richtige Vorgehensweise für ~ / .bash_profile wurde hier beantwortet:

Unterschied zwischen .bashrc und .bash_profile

if [ -r ~/.profile ]; then . ~/.profile; fi
case "$-" in *i*) if [ -r ~/.bashrc ]; then . ~/.bashrc; fi;; esac

Zum Aktivieren von Test (und Profilerstellung) können Sie dies verwenden

~ / .bash_profile:

#!/bin/bash

# ------------------------------------------------
export _DOT_BASH_PROFILE_0=`date  --rfc-3339=ns`
# ------------------------------------------------

if [ -f ~/.profile ] ; then
    . ~/.profile
fi

case "$-" in *i*) if [ -r ~/.bashrc ]; then . ~/.bashrc; fi;; esac

# ------------------------------------------------
export _DOT_BASH_PROFILE_1=`date  --rfc-3339=ns`
# ------------------------------------------------

~ / .zprofile:

#!/bin/zsh

# ------------------------------------------------
export _DOT_ZSH_PROFILE_0=`date  --rfc-3339=ns`
# ------------------------------------------------

if [ -f ~/.profile ] ; then
    . ~/.profile
fi

# no need to source, zsh already handle ~/.zshrc

###case "$-" in *i*) if [ -r ~/.zshrc ]; then . ~/.zshrc; fi;; esac

# ------------------------------------------------
export _DOT_ZSH_PROFILE_1=`date  --rfc-3339=ns`
# ------------------------------------------------

dann zum testen:

chsh -s /bin/bash

ssh localhost
env

exit

ssh localhost env

ssh -t localhost bash -i -c env


chsh -s /bin/zsh

ssh localhost
env

exit

ssh localhost env

ssh -t localhost bash -i -c env

Also sollte RVM / virtualenv in ~ / .profile gehen, IMHO

Aber das funktioniert nicht , manchmal ...

Beispielsweise funktioniert virualenvwrapper nur, wenn die Shell, auf der Xsession ausgeführt wird, eine "ursprüngliche" Bash ist (Export von BASH_VERSION).

Wenn Sie sich auf einem Dash- System befinden, funktionieren die Umgebungsvariable und die Pfadeinstellung , die Definition der virualenvwrapper- Funktion funktioniert jedoch nicht, da das Skript nicht POSIX-kompatibel ist.

Das Skript gibt keinen Fehler aus, endet jedoch ohne "Workon" -Definition.

Sie können also die Umgebung in ~ / .profile festlegen , um die korrekte Python-Ausführung vom Client aus zu ermöglichen, der direkt von X aus gestartet wurde:

export VIRTUAL_ENV="/home/mike/var/virtualenvs/myvirtualenv"
export PATH="$VIRTUAL_ENV/bin:$PATH"
unset PYTHON_HOME

https://gist.github.com/datagrok/2199506

https://www.bountysource.com/issues/9061991-setting-up-your-computer-virtualenvwrapper-linux-all

Für virualenvwrapper gibt es jedoch zwei Alternativen:

  1. Quell es in ~ / .bash_profile oder ~ / .zprofile (oder ~ / .zlogin), wenn das Terminal als Login-Shell fungiert
  2. Fügen Sie das Skript in ~ / .bashrc oder ~ / zshrc ein

Dies bedeutet, dass X-Clients (z. B. Emacs) von der Terminal-Shell aus gestartet werden sollten und nicht von der grafischen!

"Ich kann keine Befriedigung bekommen ..."

hute37
quelle
Eine völlig andere Geschichte ist das Ausführen von Diensten mit systemd. Einige mögliche Alternativen sind: Schreiben eines Wrapper- Skripts, Definieren der Umgebung in der Definitionsdatei "service" , Speichern der Umgebung in einer "env" -Datei, die in einer übergeordneten Shell bezogen werden soll. Die Dinge werden schwieriger mit RVM / virtualenv ...
hute37