Warum wird / etc / profile für nicht angemeldete Shells nicht aufgerufen?

51

Anmelde- und Nicht-Anmelde-Shell definiert als:

su - $USER # will give you a login shell
bash # will give you a non-login shell

/ etc / profile wird nicht für nicht angemeldete Shells aufgerufen, z. B. wenn Sie konsole (kde) starten. / etc / profile wird nur für Login-Shells aufgerufen.

Warum ist das so? Bitte erklären Sie, weil ich die Gründe dafür verstehen möchte.

James Mitch
quelle

Antworten:

100

/etc/profile wird nur für Login-Shells aufgerufen, da dies der spezifische Zweck ist.

Wenn Sie möchten, dass ein Befehl für interaktive Shells ausgeführt wird, bei denen es sich nicht um Anmeldeshells handelt, und Sie verwenden bash, geben Sie ihn in ~/.bashrcoder ein /etc/bash.bashrc.

Der Zweck der "Profil" -Dateien besteht darin, Befehle zu enthalten, die nur für Login-Shells ausgeführt werden sollten. Diese Dateien sind:

  • /etc/profile, wird von allen Bourne-kompatiblen Shells (einschließlich bashund dash) ausgeführt, wenn sie als Anmeldeshell gestartet werden.

  • Skripte in /etc/profile.d.

    Dies gilt für Shells im Bourne-Stil, ist jedoch nicht in der Shell-Programmdatei selbst codiert. Befehle in /etc/profilerufen sie vielmehr auf . /etc/profileEnthält beispielsweise auf meinem Ubuntu 12.04-System die folgenden Zeilen:

    if [ -d /etc/profile.d ]; then
      for i in /etc/profile.d/*.sh; do
        if [ -r $i ]; then
          . $i
        fi
      done
      unset i
    fi
    
  • .profile Wird im Ausgangsverzeichnis des Benutzers von Bourne-kompatiblen Shells ausgeführt, wenn diese als Anmeldeshell gestartet werden (sofern sie nicht überschrieben werden, siehe unten).

  • .bash_profileoder .bash_loginim Home-Verzeichnis des Benutzers. Diese werden von anderen Shells als ignoriert bash. Aber falls .bash_profilevorhanden, bashläuft es statt .profile . Wenn .bash_profilenicht vorhanden, aber .bash_loginvorhanden ist, wird dies anstelle von ausgeführt .profile.

    (Aber es ist üblich , .bash_profileoder .bash_login, wenn es vorhanden ist , geschrieben werden, um * explizit aufrufen .profile.)

    Der Vorteil von Shell-spezifischen Profildateien besteht darin, dass sie Befehle oder Syntax enthalten können, die nur für diese Shell gültig sind. Zum Beispiel kann ich den [[Evaluierungsoperator in .bash_profile/ verwenden, .bash_loginaber wenn ich ihn verwende .profileund mich dann dashals meine Shell anmelde, schlägt er fehl.

Was sollte in "Profil" -Dateien gehen

"profile" -Dateien sollten Befehle enthalten, die zu Beginn der Anmeldung nur einmal ausgeführt werden dürfen. (Dies schließt auch grafische Anmeldungen ein, da sie auch mit einer Anmeldeshell beginnen.) Wenn eine Shell interaktiv ist, ist der Benutzer, der sie ausführt, wahrscheinlich angemeldet, und daher hat sie wahrscheinlich einen Vorfahren (der sie gestartet hat oder was sie gestartet hat). oder fing damit an, etc.) das war eine Login-Shell.

Möglicherweise möchten Sie einen Befehl nur einmal ausführen, weil:

  1. Es gibt keinen Grund, es mehr als einmal pro Anmeldung auszuführen, es wäre ineffizient, oder
  2. Es würde zu einem unerwünschten Ergebnis führen, wenn es mehr als einmal pro Anmeldung ausgeführt würde.

Betrachten Sie als Beispiel für die zweite Situation, in der ein unerwünschtes Ergebnis auftreten würde, die folgenden Zeilen, die standardmäßig in jedem Benutzer angezeigt werden ~/.profile:

# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
    PATH="$HOME/bin:$PATH"
fi

Angenommen, Sie haben mit SSH eine andere Shell ausgeführt (z. B. zsh), irgendwann festgestellt, dass Sie vorübergehend zu bashIhrer Umgebung zurückkehren und diese beibehalten möchten (also basherneut ausgeführt, während Sie sich in der Shell befinden zsh), und dann ein Programm wie mcdieses ausgeführt, das eine Shell als Teil ausführt seiner Schnittstelle. Wenn bines in Ihrem Home-Ordner existiert und Ihr Benutzername ist james, ist Ihre PATHin der innersten Shell so etwas wie:

/home/james/bin:/home/james/bin:/home/james/bin:/home/james/bin:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

Das ist ineffizient und (was noch wichtiger ist) macht es schwierig, den Inhalt von zu verstehen PATH.

Dies ist jedoch keineswegs eine Katastrophe. Soweit ich das beurteilen kann, würde in der Standardkonfiguration nichts Schlimmes passieren, wenn alle "Profil" -Dateien von interaktiven Shell-Quellen stammen . Da der Zweck von "Profil" -Dateien darin besteht, Befehle zu enthalten, die nur einmal pro Anmeldung ausgeführt werden sollen , kann ein Benutzer oder Administrator einem Profil Befehle hinzufügen, die nur beim Starten einer Anmeldeshell ausgeführt werden müssen.

Wo Befehle für jede auszuführende interaktive Shell abgelegt werden

Wenn Sie verwenden bash, gibt es Dateien für Befehle, die in jeder interaktiven Shell ausgeführt werden sollen:

  • /etc/bash.bashrc
  • .bashrc im Home-Verzeichnis des Benutzers.

Dies wird am häufigsten für Befehle verwendet, die

  1. wirken sich nur auf die Umgebung der Shell aus, in der sie ausgeführt werden - nicht einmal auf Kinderschalen oder
  2. sollte auch dann ausgeführt werden, wenn dies nicht die Anmeldeshell ist.

Beispielsweise sollte die Vervollständigung von Befehlszeilenregistern im Allgemeinen aktiviert sein, unabhängig davon, ob es sich bashum die Anmeldeshell handelt oder nicht . Das erscheint also in ~/.bashrc:

if [ -f /etc/bash_completion ] && ! shopt -oq posix; then
    . /etc/bash_completion
fi

Dort gelten 1 und 2 beide: Dies überträgt sich nicht auf andere Shells, die in diesem ausgeführt werden, und die Tab-Vervollständigung sollte bashauch dann funktionieren , wenn ich mich mit einer anderen Shell angemeldet habe.

Wo Befehle für Anmelde-Shells und interaktive Nicht-Anmelde-Shells abgelegt werden

Wenn Sie basheinen Befehl in Anmelde-Shells und interaktiven Shells ausführen möchten und dies keine Anmelde-Shells sind, ist es im Allgemeinen ausreichend, ihn in /etc/bash.bashrcoder einzufügen~/.bashrc . Dies liegt daran, standardmäßig /etc/profileund ~/.profileführen Sie sie explizit. Zum Beispiel ~/.profilehat:

# if running bash
if [ -n "$BASH_VERSION" ]; then
    # include .bashrc if it exists
    if [ -f "$HOME/.bashrc" ]; then
        . "$HOME/.bashrc"
    fi
fi

(Ebenso /etc/profileQuellen /etc/bash.bashrcfür bash.)

Daher werden sowohl "profile" als auch "rc" Dateien ausgeführt, wenn Sie eine interaktive bashShell starten (unabhängig davon, ob es sich um eine Anmeldeshell handelt oder nicht).

Wo Befehle in nicht interaktiven Shells ausgeführt werden sollen

Sie möchten wahrscheinlich keine Befehle für alle nicht interaktiven Shells angeben, die ausgeführt werden sollen. Sie werden jedes Mal ausgeführt, wenn ein Skript ausgeführt wird (vorausgesetzt, das Skript wird von der Shell ausgeführt, die Sie für die Ausführung konfigurieren).

Dies kann zu erheblichen Brüchen führen. Wenn Sie dies tun und auf dem System kein anderes Administratorkonto als das von Ihnen verwendete vorhanden ist, möchten Sie möglicherweise eines erstellen. das kann es einfacher machen, Fehler zu beheben.

In bashwerden die "rc" -Dateien tatsächlich ausgeführt, unabhängig davon , ob die Shell interaktiv ist oder nicht . Oben steht jedoch:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

Wenn Sie also Befehle benötigen, die auch in nicht interaktiven Shells wie denjenigen, die zum Ausführen von Skripten ausgeführt werden, automatisch ausgeführt werden, können Sie Ihre Befehle vor diesen Zeilen einfügen.

Starten einer Login-Shell

Beim Anmelden wird eine Anmeldeshell gestartet. Wenn eine danach gestartete Shell als Login-Shell fungieren soll , starten Sie sie mit dem -lFlag (steht für l ogin ). Zum Beispiel:

Dies ist der beste Weg, um eine Login-Shell zu starten (ohne sich anzumelden), es sei denn, Sie möchten einen anderen Benutzer als Benutzer starten . Dann benutze:

  • sudo -ifür root(Verwendung sudo -sfür eine nicht angemeldete, interaktive Root-Shell)
  • sudo -u username -i für jeden Benutzer
  • su - usernamefür Nichtbenutzer root( für eine nicht angemeldete, interaktive Root-Shell verwenden)su username

Was ist eine anfängliche Anmeldeshell?

Eine anfängliche Anmeldeshell entspricht einer Anmeldeshell . Überall in dieser Antwort steht "login shell", es könnte "inital login shell" stehen (außer in diesem Abschnitt, der aufgehört hätte, Sinn zu machen).

Ein Grund für den Begriff inital login shell ist, dass login shell auch in einem anderen Sinne verwendet wird - um zu identifizieren, welches Programm als Shell verwendet wird, die bei der Anmeldung ausgeführt wird. Dies ist der Sinn der Login-Shell zu sagen:

  • " OpenBSD ‚s Standard - Login - Shell ist ksh, in Ubuntu, es ist bash."
  • Msgstr "Sie können Ihre Login - Shell mit ändernchsh ."

Weitere Lektüre

Eliah Kagan
quelle
4
Eine der besten Antworten auf alle Fragen auf einer Stack Exchange-Site.
Mark E. Haase
1
> "profile" -Dateien sollten Befehle enthalten, die zu Beginn der Anmeldung nur einmal ausgeführt werden dürfen. (Dies schließt grafische Anmeldungen ein, da sie auch mit einer Anmeldeshell beginnen.) Nein, nein, nein, nein! Das tut es absolut nicht! Alle bourne-ähnlichen Shells lesen .profile nur in interaktiven Anmeldeshellsitzungen , dh solche, die entweder mit der Option -i gestartet wurden oder mit einem steuernden Terminal verbunden sind (beides gilt nicht, wenn die Shell von einem Display-Manager gestartet wurde). Der Grund dafür ist, dass der Zweck dieser Datei darin besteht, das Terminal des Benutzers und nicht nur dessen Umgebung einzurichten . Wenn ein Display Manager tr
Eliah, ich habe den Rest von Dereks Kommentar hier wiedergegeben, aber den oben genannten Stumpf verlassen, damit er Ihre Antwortbenachrichtigung erhält, obwohl er aufgrund von Reputationsanforderungen nicht in der Lage ist, darauf zu antworten. Ich habe ihm jedoch Schreibzugriff auf den oben genannten Chatraum gewährt.
Seth
1
In bash, the "rc" files are actually run whether the shell is interactive or not. ist falsch. /etc/bash.bashrc wird von /etc/bash.profile ausgelöst.
Okwap
Okwap ist richtig, haben rc Dateien nicht in nicht-interaktiv Shell aufgerufen erhalten, dies ist dies prägnantes und genau.
Nick Allen