Dowiedz się, jakie skrypty są uruchamiane przez bash podczas uruchamiania

15

Po uruchomieniu terminala bash zauważyłem, że zmienna PATH zawiera zduplikowane wpisy. Mój terminal uruchamia powłokę logowania , więc ~/.bash_profilejest pozyskiwany, a następnie ~/.profilei ~/.bashrc. Tylko ~/.profilewewnątrz mogę utworzyć wpisy ścieżek, które są zduplikowane.

Aby być pedantycznym, jest to kolejność, w jakiej pozyskiwane są pliki, które POWINNY być pozyskiwane:

Sourced /etc/profile
Sourced /etc/bash.bashrc
Sourced .bash_profile
Sourced .profile
Sourced .bashrc

Zanim ktokolwiek oznaczy to jako duplikat „Zmienna PATH zawiera duplikaty”, czytaj dalej.

Na początku myślałem, że ma to związek z ~/.profiledwukrotnym pozyskiwaniem, więc miałem plik zapisywać do pliku dziennika za każdym razem, gdy był pozyskiwany, i, co zaskakujące, zarejestrował tylko jeden wpis, co mówi mi, że został on pobrany tylko raz. Jeszcze bardziej zaskakujący jest fakt, że kiedy komentuję wpisy, które były ~/.profile, wpisy wciąż pojawiają się w PATHzmiennej. Doprowadziło mnie to do trzech wniosków, z których jeden został szybko wykluczony:

  1. Bash ignoruje prawidłowe komentarze basha i nadal wykonuje skomentowany kod
  2. Istnieje skrypt, który odczytuje ~/.profilei ignoruje każdy kod, który drukuje dane wyjściowe (na przykład plik dziennika)
  3. Jest moja kolejna kopia, ~/.profilektóra jest pozyskiwana gdzie indziej

Po pierwsze, szybko doszedłem do wniosku, że tak nie jest ze względu na szybkie testy. Druga i trzecia opcja są tam, gdzie potrzebuję pomocy.

Jak zebrać dziennik skryptów, które są uruchamiane podczas uruchamiania mojego terminalu? Użyłem echow plikach, które sprawdziłem, aby wiedzieć, czy są one pozyskiwane przez bash, ale muszę znaleźć rozstrzygającą metodę, która śledzi wykonanie do momentu, gdy terminal jest gotowy, abym mógł zacząć pisać na nim.

Jeśli powyższe nie jest możliwe, każdy może zasugerować, gdzie indziej mogę sprawdzić, które skrypty są uruchamiane .


Przyszłe referencje

Oto skrypt, którego teraz używam do dodawania do mojej ścieżki:

function add_to_path() {
    for path in ${2//:/ }; do
        if ! [[ "${!1}" =~ "${path%/}" ]]; then # ignore last /
            new_path="$path:${!1#:}"
            export "$1"="${new_path%:}" # remove trailing :
        fi
    done
}

Używam tego w ten sposób:

add_to_path 'PATH' "/some/path/bin"

Skrypt sprawdza, czy ścieżka już istnieje w zmiennej przed jej dodaniem.

W przypadku użytkowników Zsh możesz użyć tego odpowiednika:

function add_to_path() {
    for p in ${(s.:.)2}; do
        if [[ ! "${(P)1}" =~ "${p%/}" ]]; then
            new_path="$p:${(P)1#:}"
            export "$1"="${new_path%:}"
        fi
    done
}

Edytuj 28.08.2018

Kolejną rzeczą, którą mogłem zrobić z tym skryptem, jest także poprawienie ścieżki. Na początku .bashrcpliku robię coś takiego:

_temp_path="$PATH"
PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin'
add_to_path 'PATH' "$_temp_path"
unset _temp_path

To od Ciebie PATHnależy zacząć. PATHNajpierw sprawdź, aby podjąć decyzję.

smac89
źródło
Bash czyta tylko, ~/.profile jeśli ~/.bash_profilenie istnieje ...
jasonwryan
@Jasonwryan, I źródła ~/.profilei ~/.bashrcod~/.bash_profile
smac89

Odpowiedzi:

30

Jeśli twój system ma strace, możesz wyświetlić listę plików otwartych przez powłokę, na przykład używając

echo exit | strace bash -li |& grep '^open'

( -lioznacza interaktywną powłokę logowania; używaj tylko -ido interaktywnej powłoki niezalogowanej).

Spowoduje to wyświetlenie listy plików, które powłoka otworzyła lub próbowała otworzyć. W moim systemie są one następujące:

  1. /etc/profile
  2. /etc/profile.d/*(różne skrypty w /etc/profile.d/)
  3. /home/<username>/.bash_profile (to się nie powiedzie, nie mam takiego pliku)
  4. /home/<username>/.bash_login (to się nie powiedzie, nie mam takiego pliku)
  5. /home/<username>/.profile
  6. /home/<username>/.bashrc
  7. /home/<username>/.bash_history (historia wierszy poleceń; to nie jest skrypt)
  8. /usr/share/bash-completion/bash_completion
  9. /etc/bash_completion.d/* (różne skrypty zapewniające funkcję autouzupełniania)
  10. /etc/inputrc (definiuje przypisania klawiszy; to nie jest skrypt)

Użyj, man straceaby uzyskać więcej informacji.

AlexP
źródło
Dziękuję za twój wkład, ale myślę, że coś jest nie tak z moim bash. Uruchomienie echo $0w terminalu daje -bashraczej niż oczekiwany bash. Czy masz na to jakieś sugestie?
smac89
3
@ smac89: To normalne dla powłoki logowania. Bash zachowuje się jak powłoka logowania, gdy pierwszy znak $0to myślnik -lub gdy jest wywoływany z opcją -l.
AlexP
OK, to trochę ulga. Uruchomiłem polecenie, które wydałeś, a dane wyjściowe wyglądają na bardzo skomplikowane, ale mimo to wszystkie pokazane pliki nie zawierają zduplikowanych wpisów. To prowadzi mnie do myślenia, że ​​zduplikowane wpisy pojawiają się, gdy loguję się na swoje konto po raz pierwszy, tj. Coś początkowo wyszukuje wpisy w tym pliku i czy to się dzieje ponownie, kiedy otwieram terminal? Właściwie myślę, że to może być to. Gdy loguję się na swoje konto, wpisy są pozyskiwane i ponownie, gdy otwieram terminal, proces się powtarza. Czy to brzmi możliwe?
smac89
Dlaczego nie debugujesz w staromodny sposób, umieszczając echo PATH=\""$PATH"\"na początku i na końcu .profilei .bashrc? A dlaczego nie można zrobić to, co każdy robi i ustawić ścieżkę albo całkowicie, albo, jeśli dodanie katalogu, strzeżony: echo ":$PATH:" | grep -q ":/path/to/dir:" || export PATH="$PATH:/path/to/dir"?
AlexP
4
Użyj sudo bash -c "echo exit|dtruss bash -li|& less|grep '^open'"na macOS. (wystarczy wymienić stracez dtruss)
Max COPLAN