Wie finde ich die Datei, in der eine Bash-Funktion definiert ist?


33

Ich kann nicht herausfinden, wie ich die Datei finde, in der eine Bash-Funktion definiert ist ( __git_ps1in meinem Fall).

Ich experimentierte mit declare, type, which, aber nichts sagt mir , die Quelldatei. Ich habe irgendwo gelesen, dass declareman den Dateinamen und die Zeilennummer ausdrucken kann, aber es wurde nicht erklärt wie. Die helpSeite für declaresagt es auch nicht.

Wie kann ich diese Informationen erhalten?


Wenn der Pfad zur Funktionsdatei nicht enthalten ist $PATH, funktioniert dies typenicht. Vielleicht möchten Sie es einfach mit findoder versuchen locate. locatewird viel schneller sein, da es eine bereits vorhandene Datenbank verwendet, aber es wird nicht funktionieren, wenn der Befehl erst kürzlich installiert wurde.
user628544

Antworten:


37

Wenn Sie bereit sind, die Funktion auszuführen, können Sie die Informationen abrufen, indem Sie set -xdie Ausführung verfolgen und die PS4Variable festlegen.

  1. Starten Sie bash mit --debuggeroder verwenden Sie es shopt -s extdebug, um zusätzliche Debugging-Informationen aufzuzeichnen.

  2. Legen Sie fest PS4, dass die Eingabeaufforderung beim Verfolgen gedruckt wird, um die Quellzeile anzuzeigen.

  3. Aktivieren Sie die Ablaufverfolgung.

  4. Sie können dann Ihre Funktion ausführen und erhalten für jede Zeile den Dateinamen der Funktion.

  5. Verwenden Sie set +x, um die Ablaufverfolgung zu deaktivieren.

Also für diesen Fall würden Sie laufen

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

"-x Zeigen Sie nach dem Erweitern jedes einfachen Befehls für Befehl, Groß- / Kleinschreibung, Auswahlbefehl oder Arithmetik für Befehl den erweiterten Wert von PS4 an, gefolgt von dem Befehl und seinen erweiterten Argumenten oder der zugehörigen Wortliste." Nett!
l0b0

25

Wenn Sie nicht bereit sind, die Funktion auszuführen, können Sie dennoch das Debuggen einrichten und die Informationen abrufen. Die Schritte sind

  1. starten bash --debuggeroder shopt -s extdebugbevor die Funktion definiert ist.
  2. declare -F __git_ps1

und es wird berichtet, wo die Funktion definiert ist.

Die Vorteile dieser Methode im Vergleich zum Anzeigen der kommentierten Ausführungsablaufverfolgung mit PS4 sind

  • Viel weniger Leistung
  • Es beantwortet direkt die Frage

Die Vorteile des Execution Trace sind

  • Alle aufgerufenen Funktionen auf einmal anzeigen
  • Siehe die Beziehungen zwischen aufgerufenen Funktionen
  • Siehe Rekursion

Ich empfehle nachdrücklich , shopt -s extdebugam Anfang von beiden zu stehen ~/.bashrcund ~/.bash_profiledie verschiedenen Dateien zu behandeln, die in verschiedenen Invocation- Fällen verwendet werden.


1
Es funktioniert auch, wenn nach der Definition der Funktion shopt -s extdebugaufgerufen wird. Achten Sie darauf, dass die Zeilennummern möglicherweise deaktiviert sind (ein aktueller Fehler), wenn die Funktion durch deklariert ist . eval
Stéphane Chazelas

Ich war nach einer fehlgeleiteten erledigung für vpnc. Nachdem bash --debuggerich die Fertigstellung tatsächlich auslösen musste, um die Fertigstellungsfunktion zu definieren und von zu melden declare -F _vpnc.
Harald

9

Die großartige Lösung von @ icarus funktioniert für Funktionen, sofern sie wörtlich definiert sind und nicht das Ergebnis eines evalInhalts einer anderen Datei (in der die Datei mit dem evalals Quelle angezeigt wird). Es wird nicht die Quelldatei von Aliasen, Shell-Built-Ins (wie echo) und ausführbaren Dateien (binär oder nicht) gedruckt , und ich glaube, diese Informationen sind im Allgemeinen nicht verfügbar. Einige Befehle drucken möglicherweise ihre Quelldateien (und sind möglicherweise sogar wahrheitsgemäß), entweder während der normalen Ausführung oder als Antwort auf ein Signal.

__git_ps1ist in /usr/share/git/git-prompt.shund /usr/share/git/completion/git-prompt.shauf meinem System Arch Linux definiert, daher kann es für Sie dasselbe sein.

Werfen Sie einen Blick auf den Abschnitt Aufruf von, man bashwenn Sie nach Befehlen suchen möchten, die speziell am Anfang der Shell erstellt wurden. Diese können andere Dateien enthalten, die wiederum andere Dateien enthalten.


Kann man eine Liste der Dateien bekommen, die beim Start bezogen werden bash?
Pfnuesel

@pfnuesel - es liegt an dir. Die Standardeinstellungen sind in $HOME/.bashrcund in $HOME/.profile. Siehe: linuxfromscratch.org/blfs/view/svn/postlfs/profile.html. Hier erfahren Sie , wann und wie die einzelnen Dateien bezogen werden.
Joe

2
@Joe gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html ist eine viel bessere Referenz. /etc/profile, $HOME/.bash_profile, $HOME/.bash_login, Und der Inhalt $ENVund $BASH_ENVNotwendigkeit zu Ihrer Liste hinzugefügt werden.
Ikarus

@icarus - Danke. Das ist eine bessere Erklärung.
Joe

8

Es scheint nicht möglich zu sein bash, aber es ist in zsh:

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

Die Frage gibt bash an ...
Jeff Schaller

4
@JeffSchaller: Die naheliegende Möglichkeit, diese Antwort zu verwenden, besteht darin, zsh so einzurichten, dass dieselben Dateien wie bei bash als Quelle verwendet werden, und dann die Definition zu finden. Diese Antwort ist darauf hindeutet , nicht zu zsh wechseln, nur , dass es offensichtlich ein nützliches Werkzeug , das Shell - Syntax besser versteht als generische Instrumente wie find/ locate/ grep.
Peter Cordes

Ich würde dann, @PeterCordes, behaupten, dass diese Antwort derzeit nicht das tut, was Sie sagen, um die Frage zu beantworten. Ich weiß nicht, ob zsh nativ dieselben Dateien liest wie bash.
Jeff Schaller

@ JeffSchaller: Einverstanden ist diese Antwort verbesserungswürdig. zsh liest mit ziemlicher Sicherheit nicht ~/.whateverstandardmäßig die gleichen Dateien wie bash und gibt nur nützliche Antworten für Funktionen, die an gemeinsam genutzten Speicherorten wie in diesem Fall definiert sind und in ~/.bashrcoder was auch immer nicht neu definiert wurden .
Peter Cordes

-1

Deklarieren Sie eine Funktion mit demselben Namen und setzen Sie sie so früh wie möglich auf readonly, und aktivieren Sie dann den xtrace-Modus.

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

Wenn Sie sich danach anmelden, werden Trace-Informationen angezeigt, die die Beschaffung von Dateien umfassen. In dem Moment, in dem versucht wird, die vorhandene schreibgeschützte Funktion zu deklarieren, wird eine Fehlermeldung angezeigt. Die zuletzt bezogene Datei sollte die gesuchte Deklaration enthalten.

Möglicherweise müssen Sie dies in das System-Bash-Profil einfügen. Denken Sie auch daran, die Änderungen rückgängig zu machen, nachdem Sie den Täter gefunden haben.


-3

Hast du das probiert?

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

oder einen der anderen Befehle, die hier zu finden sind:

Wie finde ich alle Dateien, die bestimmten Text enthalten, unter Linux? | Paketüberfluss

Es scheint, dass ich Ihnen mehr Erklärungen geben muss. Ihre Frage lautet "" Wenn Sie also den folgenden Befehl ausführen, sollte er alle Dateien zurückgeben, in denen eine Bash - Funktion definiert ist.

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

BASH-Programmierung - Funktionen | Linux-Dokumentationsprojekt


1
Nur-Link-Antworten werden absolut nicht empfohlen. Bitte fügen Sie eine Erklärung hinzu.
Heemayl
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.