In my verwende .profile
ich den folgenden Code, um sicherzustellen, dass Bash-bezogene Aliase und Funktionen nur bezogen werden, wenn die Anmeldeshell tatsächlich Bash ist :
# If the current (login) shell is Bash, then
if [ "${BASH_VERSION:-}" ]; then
# source ~/.bashrc if it exists.
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi
Ich bin gerade dabei, meine Shell-Konfigurationsdateien, Skripte und Funktionen der Versionskontrolle zu unterstellen. Ich habe vor kurzem auch damit begonnen, gelegentliche Bashisms aus Shell-Skripten zu entfernen, die nicht von Bash-spezifischen Funktionen profitieren, z . B. Ersetzen function funcname()
durch funcname()
.
Für mein Shell-Datei-Repository habe ich einen Pre-Commit- Hook konfiguriert , der das checkbashisms
Dienstprogramm aus Debians devscripts-Paket für jede sh
Datei im Repository ausführt, um sicherzustellen, dass ich nicht versehentlich die Bash-spezifische Syntax einführe. Dies führt jedoch zu einem Fehler für meine .profile
:
possible bashism in .profile line 51 ($BASH_SOMETHING):
if [ "${BASH_VERSION:-}" ]; then
Ich habe mich gefragt, ob es eine Möglichkeit gibt, zu überprüfen, welche Shell ausgeführt wird, die keine Warnung auslöst checkbashisms
.
Ich habe die Liste der von POSIX aufgelisteten Shell-bezogenen Variablen überprüft, in der Hoffnung, dass eine davon verwendet werden kann, um die aktuelle Shell anzuzeigen. Ich habe mir auch die Variablen in einer interaktiven Dash-Shell angesehen, aber auch hier keinen geeigneten Kandidaten gefunden.
Im Moment habe ich ausgeschlossen, .profile
von verarbeitet zu werden checkbashisms
; Da es sich um eine kleine Datei handelt, ist es nicht schwierig, sie manuell zu überprüfen. Nachdem ich das Problem untersucht habe, möchte ich dennoch wissen, ob es eine POSIX-kompatible Methode gibt, mit der ermittelt werden kann, welche Shell ausgeführt wird (oder zumindest eine Methode, die nicht checkbashisms
zum Fehlschlagen führt).
Weiterer Hintergrund / Klarstellung
Einer der Gründe, warum ich meine Shell-Konfigurationsdateien der Versionskontrolle unterstelle, ist die regelmäßige Konfiguration meiner Umgebung auf allen Systemen, auf denen ich mich derzeit anmelde: Cygwin, Ubuntu und CentOS (beide 5 und 7, mit Active Directory für Benutzer) Authentifizierung). Ich melde mich am häufigsten über X Windows / Desktop-Umgebungen und SSH für Remote-Hosts an. Ich möchte jedoch, dass dies zukunftssicher ist und möglichst wenig von Systemabhängigkeiten und anderen Tools abhängt.
Ich habe checkbashisms
als einfache, automatisierte Überprüfung die Syntax meiner Shell-bezogenen Dateien verwendet. Es ist kein perfektes Tool, z. B. habe ich bereits einen Patch darauf angewendet, damit er sich nicht über die Verwendung command -v
in meinen Skripten beschwert . Während der Recherche habe ich erfahren, dass der eigentliche Zweck des Programms darin besteht, die Einhaltung der Debian-Richtlinien sicherzustellen, die meines Wissens eher auf POSIX 2004 als auf 2008 (oder dessen Revision 2013) basieren.
quelle
.bash_profile
, das sowohl.profile
(bedingt) als auch Quellen enthält.bashrc
.Antworten:
Ihre
Code ist vollständig POSIX-konform und die beste Methode, um zu überprüfen, ob Sie gerade ausgeführt werden
bash
. Natürlich ist die$BASH_VERSION
Variable bash-spezifisch, aber genau deshalb verwenden Sie sie! Um zu überprüfen, dass Sie laufenbash
!Beachten Sie, dass festgelegt
$BASH_VERSION
wird, obbash
alsbash
oder aufgerufen wirdsh
. Sobald Sie bestätigt haben, dass Sie ausgeführt werdenbash
, können Sie[ -o posix ]
als Indikator verwenden, dass die Shell aufgerufen wurde alssh
(obwohl diese Option auch festgelegt ist, wenn sich POSIXLY_CORRECT in der Umgebungbash
befindet-o posix
oder mit oder mit SHELLOPTS = posix in der Umgebung aufgerufen wird. Aber in all diesen Fällenbash
wird sich so verhalten, als ob genannt alssh
).Eine andere Variable, die Sie stattdessen verwenden könnten
$BASH_VERSION
und diecheckbashism
sich nicht zu beschweren scheint, es sei denn, Sie haben die-x
Option bestanden$BASH
. Dies ist auch spezifisch fürbash
eine, mit der Sie auch bestimmen können, ob Sie ausgeführt werdenbash
oder nicht.Ich würde auch behaupten, es ist nicht wirklich eine ordnungsgemäße Verwendung
checkbashisms
.checkbashisms
ist ein Werkzeug, mit dem Sie portablesh
Skripte schreiben können (gemäß dersh
Spezifikation in der Debian-Richtlinie, einer Obermenge von POSIX). Es hilft dabei, nicht standardmäßige Syntax zu identifizieren, die von Leuten eingeführt wird, die Skripte auf Systemen schreiben, auf denensh
ein Symlink zu istbash
.A
.profile
wird von verschiedenen Shells interpretiert, von denen viele nicht POSIX-kompatibel sind. Im Allgemeinen verwenden Sie nichtsh
als Login - Shell, aber Muscheln mögenzsh
,fish
oderbash
mit erweiterten interaktiven Funktionen.bash
undzsh
, wenn sie nicht als aufgerufen werdensh
und wenn ihre jeweilige Profilsitzungsdatei (.bash_profile
,.zprofile
) nicht POSIX-konform ist (insbesonderezsh
), aber dennoch gelesen wird.profile
.Es ist also keine POSIX-Syntax, die Sie möchten,
.profile
sondern eine mit POSIX (fürsh
) kompatible Syntax ,bash
undzsh
falls Sie jemals diese Shells verwenden möchten (möglicherweise liest sogar Bourne, wie die Bourne-Shell es auch liest,.profile
aber auf Linux-basierten Systemen nicht häufig vorkommt) ).checkbashisms
Dies würde Ihnen definitiv dabei helfen, Bashismen herauszufinden, könnte jedoch nicht auf eine POSIX-Syntax hinweisen, die mitzsh
oder nicht kompatibel istbash
.Wenn Sie hier
bash
-spezifischen Code verwenden möchten (wie die Umgehung diesesbash
Fehlers, bei dem keine~/.bashrc
interaktiven Anmeldeshells eingelesen werden ), ist es besser, dies zu~/.bash_profile
tun (vor oder nach dem Sourcing,~/.profile
in dem Sie Ihre gemeinsame Sitzung abgelegt haben) Initialisierungen).quelle
checkbashisms
der verwendeten Variablen.$0
für diesen speziellen Fall?sh
und einer anderen Shell alssh
.dash
andere Nicht-Bash-Shell fälschlicherweise mit aufgerufen wurdeargv[0] == "bash"
, was völlig legal ist, wenn es unwahrscheinlich ist.Normalerweise verwendet man
$0
zu diesem Zweck. Auf der von Ihnen verlinkten Seite steht:quelle
$0
den Namen eines Shell-Skripts gewöhnt, dass ich vergessen habe, dass es auch auf die aktuelle Shell verweisen kann. Vielen Dank!exec
Familie verwendet, da sie es dem aufrufenden Programm ermöglichen, die Binärdatei zu identifizieren, die getrennt von der als Argument zu übergebenden Zeichenfolge ausgeführt werden soll 0.Normalerweise gibt die Umgebungsvariable SHELL die Standard-Shell an. Sie müssen die .bashrc-Datei nicht manuell entpacken (nicht wahr, siehe Update unten). Bash sollte dies automatisch tun und sicherstellen, dass sie sich im $ HOME-Verzeichnis befindet.
Die andere Möglichkeit ist, etwas zu tun wie:
Dadurch erfahren Sie, mit welchem Befehl (ohne Argumente, mit = ohne Wert werden keine Spaltenüberschriften angezeigt) der aktuelle Prozess ausgeführt wird. Beispielausgabe:
AKTUALISIEREN:
Ich stehe korrigiert! :)
Die .bashrc-Datei wird nicht immer bezogen, wie in den Kommentaren unten und /programming/415403/ angegeben
Sie können also Ihre .bashrc-Datei nach .bash_profile verschieben und prüfen, ob dies funktioniert, ohne den Test durchführen zu müssen. Wenn nicht, haben Sie den obigen Test.
quelle
.bashrc
wird eigentlich nicht von einer Login-Shell bezogen sondern.profile
(sofern vorhanden) oder.bash_profile
sind.SHELL
wird von POSIX nicht spezifiziert und leider auch nicht diecmd
Formatoption fürps
.ps -o cmd= $$
die$SHELL
Variable , obwohl sie eigentlich überall funktionieren sollte, völlig irrelevant ist. Dies ist die Standard-Shell des Benutzers und hat keinen Einfluss darauf, welche Shell gerade ausgeführt wird oder welche Shell ein Shell-Skript ausführt.~/.profile
wenn sie als Login-Shells gestartet werden. So könnte zum Beispiel dein$SHELL
seincsh
und du rennstbash -l
. Das wird bash als Login-Shell starten, es wird also gelesen~/.profile
, aber dein$SHELL
Wille zeigt immer noch aufcsh
. Außerdem wird.profile
möglicherweise explizit ein anderes Skript verwendet. Da das OP ein Höchstmaß an Robustheit anstrebt, sollten alle Arten von Fällen in Betracht gezogen werden. In jedem Fall werden$SHELL
keine nützlichen Informationen zur aktuell ausgeführten Shell bereitgestellt.SHELL
nicht von POSIX angegeben zu werden: pubs.opengroup.org/onlinepubs/9699919799/basedefs/…Die Frage fragt nach der Anmeldeshell des Benutzers sowie nach der aktuellen Shell in einer Weise, die beschwichtigt
checkbashisms
. Wenn das die Shell sein soll, auf der sich der Benutzer angemeldet hat, würde ich die von/etc/passwd
zBBenutzer können natürlich nach dem Anmelden eine neue Shell starten. Wenn eine bash ist und die andere nicht, können Tests der Umgebungsvariablen der bash möglicherweise nicht hilfreich sein.
Einige möchten möglicherweise
getent
eher als nur diepasswd
Datei verwenden (aber das würde nicht im Rahmen der Frage liegen).Basierend auf dem Kommentar zu LDAP und dem Vorschlag für könnte
logname
diese alternative Form verwendet werden:Beim Testen ist mir aufgefallen, dass
logname
die Eingabe nicht umgeleitet werden soll (daher habe ich den Ausdruck aufgeteilt gelassen). Eine kurze Überprüfunggetent
sollte auf den genannten Plattformen funktionieren (obwohl dies in der ursprünglichen Frage vorgesehen sein sollte):quelle
$(logname)
).id
ist eine andere Wahl, ob eine Variable verwendet oder vom Benutzer geändert werden soll.$(logname)
, nicht$LOGNAME
. Die Benutzer-ID und die Anmeldeshell werden beide von dem Benutzernamen abgeleitet, der beim Anmelden verwendet wird. Sie können nur auf Systemen von der Benutzer-ID zur Anmeldeshell zurückkehren, auf denen nur ein Benutzername pro Benutzer-ID vorhanden ist. Oder IOW, der Primärschlüssel in der Benutzerdatenbank ist der Benutzername, nicht die UID.