Jak znaleźć plik, w którym zdefiniowano funkcję bash?


33

Nie mogę dowiedzieć się, jak znaleźć plik, w którym zdefiniowano funkcję bash ( __git_ps1w moim przypadku).

I eksperymentował z declare, type, which, ale nic mi mówi plik źródłowy. Czytałem gdzieś, gdzie declaremożna wydrukować nazwę pliku i numer linii, ale nie wyjaśniono, jak to zrobić. helpAktualizacja declarenie mówi, albo.

Jak mogę uzyskać te informacje?


Jeśli ścieżka do pliku funkcji nie jest uwzględniona $PATH, typenie będzie działać. Możesz spróbować po prostu użyć findlub locate. locatebędzie znacznie szybszy, ponieważ wykorzystuje wcześniej istniejącą bazę danych, ale nie będzie działać, jeśli polecenie zostało zainstalowane niedawno.
user628544,

Odpowiedzi:


37

Jeśli jesteś przygotowany do uruchomienia funkcji, możesz uzyskać informacje, używając set -xdo śledzenia wykonania i ustawienia PS4zmiennej.

  1. Rozpocznij bash --debuggerlub użyj, shopt -s extdebugaby zapisać dodatkowe informacje debugowania.

  2. Ustaw PS4„monit” drukowany podczas śledzenia, aby pokazać linię źródłową.

  3. Włącz śledzenie.

  4. możesz następnie uruchomić swoją funkcję i dla każdej linii otrzymasz nazwę pliku funkcji.

  5. Użyj, set +xaby wyłączyć śledzenie.

Więc w tym przypadku uciekłbyś

bash --debugger
PS4='+ ${BASH_SOURCE[0]} '
set -x ; __git_ps1 ; set +x

„-x Po rozwinięciu każdego prostego polecenia dla polecenia, polecenia przypadku, polecenia wyboru lub arytmetyki polecenia, wyświetl rozwiniętą wartość PS4, a następnie polecenie i jego rozwinięte argumenty lub powiązaną listę słów.” Miły!
l0b0,

25

Jeśli nie chcesz uruchomić tej funkcji, nadal możesz skonfigurować debugowanie i uzyskać informacje. Kroki są

  1. uruchomić bash --debuggerlub shopt -s extdebugprzed zdefiniowaniem funkcji.
  2. declare -F __git_ps1

i poinformuje, gdzie funkcja jest zdefiniowana.

Zalety tej metody w porównaniu z podglądem śledzenia wykonania z adnotacjami w PS4 są

  • Dużo mniejsza wydajność
  • Odpowiada bezpośrednio na pytanie

Zalety śledzenia wykonania są

  • Zobacz wszystkie wywoływane funkcje jednocześnie
  • Zobacz relacje między wywoływanymi funkcjami
  • Zobacz rekurencję

Ja zdecydowanie polecam uwzględniając shopt -s extdebugna początku zarówno ~/.bashrci ~/.bash_profilena pokrycie różnych plików używanych w różnych inwokacja przypadkach.


1
Działa również, jeśli shopt -s extdebugzostanie wywołany po zdefiniowaniu funkcji. Uwaga: numery linii mogą być wyłączone (bieżący błąd), jeśli funkcja zostanie zadeklarowana poprzez eval.
Stéphane Chazelas

Byłem po nieudanym zakończeniu vpnc. Po tym, bash --debuggerjak musiałem aktywować ukończenie, aby zdefiniować funkcję uzupełniania i uzyskać raport z declare -F _vpnc.
Harald

9

Świetne rozwiązanie @ icarus działa dla funkcji, o ile są one zdefiniowane dosłownie, a nie wynik evalzawartości innego pliku (w którym plik z evalzostanie wyświetlony jako źródło). Nie będzie drukować pliku źródłowego aliasów, wbudowanych powłok (jak echo) i plików wykonywalnych (binarnych lub nie) i uważam, że te informacje nie są ogólnie dostępne. Niektóre polecenia mogą wydrukować swoje pliki źródłowe (a nawet mogą być zgodne z prawdą), w trakcie normalnego wykonania lub w odpowiedzi na sygnał.

__git_ps1jest zdefiniowany w /usr/share/git/git-prompt.shi /usr/share/git/completion/git-prompt.shw moim systemie, Arch Linux, więc może to być to samo dla Ciebie.

Zajrzyj do sekcji Wywołanie,man bash jeśli chcesz poszukać poleceń specjalnie na początku powłoki - mogą one pozyskiwać inne pliki, które z kolei źródło innych plików.


Czy można uzyskać listę plików, które są pozyskiwane podczas uruchamiania bash?
pfnuesel

@pfnuesel - to zależy od Ciebie. Domyślne są w $HOME/.bashrci w $HOME/.profile. Zobacz: linuxfromscratch.org/blfs/view/svn/postlfs/profile.html, który wyjaśnia niektóre szczegóły dotyczące tego, kiedy i jak pozyskiwany jest każdy plik.
Joe

2
@Joe gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html jest znacznie lepszym źródłem informacji. /etc/profile, $HOME/.bash_profile, $HOME/.bash_login, Oraz treść $ENVi $BASH_ENVmuszą być dodany do listy.
icarus

@icarus - Dzięki. To lepsze wytłumaczenie.
Joe

8

Nie wydaje się to możliwe bash, ale jest w zsh:

$ type __git_ps1
> __git_ps1 is a shell function from /usr/share/git/git-prompt.sh

Pytanie określa bash ...
Jeff Schaller

4
@JeffSchaller: Oczywistym sposobem na użycie tej odpowiedzi jest skonfigurowanie zsh tak, aby pobierał te same pliki, co bash, a następnie używałby go do znalezienia definicji. Ta odpowiedź nie sugeruje przejścia na zsh, tylko że jest to oczywiście przydatne narzędzie, które lepiej rozumie składnię powłoki niż ogólne narzędzia takie jak find/ locate/ grep.
Peter Cordes,

Twierdziłbym zatem, @PeterCordes, że ta odpowiedź obecnie nie robi tego, co według ciebie należy zrobić, aby odpowiedzieć na Pytanie. Nie wiem, czy zsh natywnie czyta te same pliki, co bash.
Jeff Schaller

@JeffSchaller: Zgodził się, że odpowiedź wymaga poprawy. zsh prawie na pewno nie odczytuje ~/.whateverdomyślnie tych samych plików, co bash, i daje przydatne odpowiedzi tylko dla funkcji zdefiniowanych we wspólnych lokalizacjach, takich jak w tym przypadku, które nie są ponownie zdefiniowane ~/.bashrcani nic takiego .
Peter Cordes,

-1

Zadeklaruj funkcję o tej samej nazwie i ustaw ją tylko do odczytu tak wcześnie, jak to możliwe, a następnie włącz tryb xtrace, taki jak:

__git_ps1(){ :;}
readonly -f __git_ps1
set -x

Następnie po zalogowaniu zobaczysz informacje śledzenia, które obejmują pozyskiwanie plików. W momencie próby deklaracji istniejącej funkcji tylko do odczytu pojawi się komunikat o błędzie. Ostatni pobrany plik powinien zawierać deklarację, której szukasz.

Może być konieczne umieszczenie tego w profilu bash systemu. Pamiętaj również, aby cofnąć zmiany po znalezieniu sprawcy.


-3

Próbowałeś tego?

grep -rnw '/path/to/somewhere/' -e "pattern" 

lub dowolne z innych dostępnych tutaj poleceń:

Jak znaleźć wszystkie pliki zawierające określony tekst w systemie Linux? | Przepełnienie stosu

Wydaje się, że muszę ci wyjaśnić więcej. Twoje pytanie brzmi: „Jeśli więc uruchomisz następujące polecenie, powinno ono zwrócić wszystkie pliki, w których zdefiniowano funkcję bash.

grep -rnw 'Path2Search' -e "#!/bin/bash"

Programowanie BASH - Funkcje | Projekt dokumentacji systemu Linux


1
Odpowiedzi tylko na link nie są absolutnie zalecane. Dodaj wyjaśnienie.
heemayl
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.