Doppelte Einträge in $ PATH ein Problem?

45

Ich beschaffe Bashrc's von einigen meiner Freunde. Daher habe ich doppelte Einträge in meiner $ PATH-Variablen. Ich bin nicht sicher, ob dies das Problem für Befehle ist, deren Start lange dauert. Wie funktioniert $ PATH intern in Bash? Verlangsamt mehr PFADE meine Startzeit?

balki
quelle

Antworten:

42

Mehr Einträge in zu haben, $PATHverlangsamt Ihren Start nicht direkt, aber jedes Mal, wenn Sie einen bestimmten Befehl in einer Shell-Sitzung zum ersten Mal ausführen (nicht jedes Mal, wenn Sie den Befehl ausführen, da bash einen Cache verwaltet). Die Verlangsamung ist selten wahrnehmbar, es sei denn, Sie haben ein besonders langsames Dateisystem (z. B. NFS, Samba oder ein anderes Netzwerkdateisystem oder Cygwin).

Doppelte Einträge sind auch etwas ärgerlich, wenn Sie Ihre $PATHvisuellen Daten überprüfen. Sie müssen mehr Cruft durchwaten.

Es ist einfach genug, doppelte Einträge zu vermeiden.

case ":$PATH:" in
  *":$new_entry:"*) :;; # already there
  *) PATH="$new_entry:$PATH";; # or PATH="$PATH:$new_entry"
esac

Anmerkung: Wenn Sie das Shell-Skript eines anderen Benutzers verwenden, müssen Sie den von ihm geschriebenen Code ausführen. Mit anderen Worten, Sie gewähren Ihren Freunden jederzeit Zugriff auf Ihr Konto.

Randnotiz: .bashrcIst nicht der richtige Ort zum Festlegen $PATHoder einer anderen Umgebungsvariablen. Umgebungsvariablen sollten in gesetzt werden ~/.profile. Siehe Welche Setup-Dateien sollten zum Einrichten von Umgebungsvariablen mit bash verwendet werden? , Unterschied zwischen .bashrc und .bash_profile .

Gilles 'SO - hör auf böse zu sein'
quelle
8
+1: Ich kann nicht genug Nachdruck darauf legen, dass "Ihren Freunden Zugriff auf Ihr Konto gewährt". Selbst wenn es keinen Versuch gibt, Ihnen Schaden zuzufügen, könnte das Drehbuch genau das sein, was sie brauchen, und Sie können trotzdem zu Mittag essen, wenn Sie es beschaffen.
msw
Ein mögliches Problem bei dieser Lösung ist, dass, wenn $ new_entry bereits der erste Eintrag in PATH ist, ": $ new_entry:" nicht übereinstimmt. Ich habe dies in meinem Profil durch Ausschließen des anfänglichen Doppelpunkts ":" behoben.
Jeff Bauer
@ JeffBauer Ich sehe das Problem nicht. Ich benutze case :$PATH:und nicht case $PATHso, dass es passt, auch wenn der Eintrag zuerst oder zuletzt ist.
Gilles 'SO - hör auf böse zu sein'
31

Ich habe gesehen, wie Leute Duplikate von ihrer PATH-Variablen mit awkund so etwas aufräumen :

PATH=$(printf "%s" "$PATH" | awk -v RS=':' '!a[$1]++ { if (NR > 1) printf RS; printf $1 }')

Sie könnten versuchen, dies zu Ihrem eigenen bashrc hinzuzufügen, und sicherstellen, dass Sie die anderen Dateien irgendwo als Quelle haben, bevor Sie sie ausführen.

Eine Alternative wäre die Verwendung despathmerge Dienstprogramms.

Was Ihr Geschwindigkeitsproblem betrifft, hat dies keine nennenswerten Auswirkungen auf die Startzeit der Shell. Es kann jedoch einige Zeit für das Ausfüllen von Registerkarten für Befehle einsparen, insbesondere wenn der Befehl nicht im Pfad gefunden wird und diese wiederholt durchsucht werden Ordner, die danach suchen.

Ein Hinweis zur Sicherheit: Sie sollten Gilles 'Warnungen bezüglich der Sicherheit hier wirklich beachten . Durch das Auffinden einer Datei, die einem anderen Benutzer gehört, geben Sie diesen Benutzern eine kostenlose Berechtigung, bei jedem Start einer Shell ihren eigenen Code als Benutzer auszuführen. Wenn Sie diesen Benutzern Ihr Kennwort nicht anvertrauen, sollten Sie ihre Shell-Dateien nicht herunterladen.

Caleb
quelle
6
Ich mag den awk-Einzeiler, aber er gibt ein abschließendes ORS ':' aus. Also PATH=$(echo "$PATH" | awk -v RS=':' -v ORS=":" '!a[$1]++{if (NR > 1) printf ORS; printf $a[$1]}')
änderte
Das Nachziehen :ist nicht nur ein kosmetisches Problem. Es ist dasselbe wie das Hinzufügen .zu Ihrem Pfad, was möglicherweise gefährlich ist.
wisbucky
Ich habe die Antwort bearbeitet, um die Korrektur von gkb0986 einzuschließen.
Tim Lesher
@TimLesher Der Grund würde ich nie als in herausgegeben von Antwort ist , dass es keine Arbeit für mich tut .... und das Original , ohne es funktioniert (einschließlich nicht einen nachgestellten Separator zu verlassen. Ich weiß nicht , was der Unterschied ist , .
Caleb
1
@ gkb0986 Diese Lösung schlägt immer noch fehl, wenn der Pfad ein Leerzeichen enthält, z. B. PATH = / bin: / foo \ bar: / usr / bin. Ich habe bei unix.stackexchange.com/a/124517/106102
maharvey67
13

Basierend auf der Antwort von @Gilles können Sie sie in eine Funktion einschließen, um die Eingabe zu minimieren:

function addToPATH {
  case ":$PATH:" in
    *":$1:"*) :;; # already there
    *) PATH="$1:$PATH";; # or PATH="$PATH:$1"
  esac
}

addToPATH /Applications/AIRSDK_Compiler/bin
addToPATH ~/.local/lib/npm/bin
hwde
quelle
1
Die praktischste Antwort (vielleicht auf hohem Niveau).
ijoseph
3

Es wird nur die erste Übereinstimmung $PATHausgeführt, sodass nachfolgende Einträge danach nicht mehr verarbeitet werden. Aus diesem Grund sollten Sie manchmal die Reihenfolge der Einträge in $PATHIhrer Umgebung ändern, damit sich Ihre Umgebung wie erwartet verhält.

Um Ihre Frage zu beantworten: Dies sollte nicht die Ursache für einen langsamen Start sein.

Rajish
quelle
1
Es dauert jedoch länger, wenn ich einen nicht vorhandenen Befehl eingebe. Derselbe Ordner wird zweimal nach dem Befehl durchsucht.
Balki
@balki Meinen Sie damit, einen Befehl auszuführen TAB? In diesem Fall sollten Sie prüfen, ob Ihre vollständige Definition nicht so aussieht complete -c which -a. Sie sollten den -aParameter löschen . Sie können das überprüfen , indem Sie den Befehl ausgeben: complete | grep which.
Rajish
Es könnte immer noch ein Problem sein, wenn dasselbe Verzeichnis durchsucht wird, in dem es sich nicht mehrmals befindet, bevor es gefunden wird.
Random832
-1

Um doppelte Einträge in meinem PATH zu vermeiden, musste ich in BOTH ~ / .bash_profile und ~ / .bashrc Folgendes einfügen:

PATH=$(echo $(sed 's/:/\n/g' <<< $PATH | sort | uniq) | sed -e 's/\s/':'/g')

Der Hauptnachteil ist, dass es PATH-Einträge sortiert, aber ich denke, ich kann damit leben.

John Reynolds
quelle
Die Reihenfolge der Suche PATH ist ziemlich wichtig.
Steven Shaw