Como encontrar o arquivo em que uma função bash está definida?

33

Não consigo descobrir como encontrar o arquivo onde uma função bash está definida ( __git_ps1no meu caso).

Eu experimentei declare,type , which, mas nada me diz que o arquivo de origem. Eu li em algum lugar que declarepode imprimir o nome do arquivo e o número da linha, mas não foi explicado como. A helppágina para declaretambém não diz isso.

Como posso obter essas informações?

Alexey
fonte
Se o caminho para o arquivo da função não estiver incluído $PATH, typenão funcionará. Você pode tentar apenas usar findou locate. locateserá muito mais rápido, pois usa um banco de dados pré-existente, mas não funcionará se o comando foi instalado recentemente.
user628544
Relacionado: unix.stackexchange.com/q/322459/117549
Jeff Schaller

Respostas:

37

Se você estiver preparado para executar a função, poderá obter as informações usando set -xpara rastrear a execução e definir a PS4variável.

  1. Inicie o bash com --debuggerou use-o shopt -s extdebugpara registrar informações extras sobre depuração.

  2. Defina PS4o 'prompt' impresso ao rastrear para mostrar a linha de origem.

  3. Ative o rastreamento.

  4. você pode executar sua função e, para cada linha, obterá o nome do arquivo da função.

  5. use set +xpara desativar o rastreamento.

Então, nesse caso, você executaria

bash --debugger
PS4='+ ${BASH_SOURCE[0]} '
set -x ; __git_ps1 ; set +x
Icaro
fonte
"-x Após expandir cada comando simples, para comando, comando caso, selecione comando ou aritmética para comando, exiba o valor expandido do PS4, seguido pelo comando e seus argumentos expandidos ou lista de palavras associada." Agradável!
l0b0
25

Se você não estiver disposto a executar a função, ainda poderá configurar a depuração e obter as informações. Os passos são

  1. iniciar bash --debuggerou shopt -s extdebugantes que a função seja definida.
  2. declare -F __git_ps1

e relatará onde a função está definida.

As vantagens deste método em comparação com o rastreamento de execução anotado no PS4 são

  • Muito menos produção
  • Responde diretamente à pergunta

As vantagens do rastreamento de execução são

  • Veja todas as funções chamadas de uma só vez
  • Veja as relações entre funções chamadas
  • Ver recursão

Eu recomendo fortemente ter shopt -s extdebugno início de ambos ~/.bashrce ~/.bash_profilecobrir os diferentes arquivos usados ​​em diferentes casos de invocação .

Icaro
fonte
1
Também funciona se shopt -s extdebugfor chamado depois que a função for definida. Cuidado: os números de linha podem estar desativados (um erro atual) se a função for declarada eval.
Stéphane Chazelas
Eu estava após uma conclusão equivocada do vpnc. Depois bash --debugger, tive que realmente ativar a conclusão para definir a função de conclusão e relatá-la declare -F _vpnc.
Harald
9

A ótima solução do @ icarus funciona para funções, desde que sejam definidas literalmente e não o resultado de um evalconteúdo de outro arquivo (no qual o arquivo com o evalserá exibido como fonte). Ele não imprimirá o arquivo de origem de aliases, embutidos do shell (como echo) e executáveis ​​(binários ou não), e acredito que essas informações não estejam disponíveis em geral. Alguns comandos podem imprimir seus arquivos de origem (e podem até ser verdadeiros), no decorrer da execução normal ou em resposta a um sinal.

__git_ps1é definido em /usr/share/git/git-prompt.she /usr/share/git/completion/git-prompt.shno meu sistema, Arch Linux, por isso pode ser o mesmo para você.

Dê uma olhada na seção Invocação , man bashcaso deseje procurar comandos originados especificamente no início do shell - eles podem originar outros arquivos que, por sua vez, originam outros arquivos.

l0b0
fonte
Pode-se obter uma lista de arquivos originados na inicialização bash?
pfnuesel
@pfnuesel - depende de você. Os padrões estão dentro $HOME/.bashrce dentro $HOME/.profile. Veja: linuxfromscratch.org/blfs/view/svn/postlfs/profile.html, que explica alguns detalhes de quando e como cada arquivo é originado.
19416 Joe
2
@Joe gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html é uma referência muito melhor. /etc/profile, $HOME/.bash_profile, $HOME/.bash_login, E o conteúdo do $ENVe $BASH_ENVnecessidade de ser adicionado à sua lista.
icarus
@icarus - Obrigado. Essa é uma explicação melhor.
20916 Joe
8

Não parece possível bash, mas está em zsh:

$ type __git_ps1
> __git_ps1 is a shell function from /usr/share/git/git-prompt.sh
pfnuesel
fonte
A pergunta especifica bash ...
Jeff Schaller
4
@JeffSchaller: A maneira óbvia de usar esta resposta é configurar o zsh para obter os mesmos arquivos que o bash usaria e depois usá-lo para encontrar a definição. Esta resposta não está sugerindo a mudança para o zsh, apenas que obviamente é uma ferramenta útil que entende a sintaxe do shell melhor do que ferramentas genéricas como find/ locate/ grep.
Peter Cordes
Eu diria, então, @ PeterCordes, que esta resposta atualmente não faz o que você diz que deve fazer para responder à pergunta. Não sei se o zsh lê nativamente os mesmos arquivos que o bash.
Jeff Schaller
@ JeffSchaller: Concordou que esta resposta precisa de melhorias. O zsh quase certamente não lê os mesmos ~/.whateverarquivos que o bash, por padrão, e apenas fornece respostas úteis para funções definidas em locais compartilhados, como neste caso, que não são redefinidas ~/.bashrcou o que seja.
Peter Cordes
-1

Declare uma função com o mesmo nome e defina-a somente o mais cedo possível e ative o modo xtrace, algo como:

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

Depois disso, ao fazer o login, você verá informações de rastreamento que incluem o fornecimento de arquivos. No momento em que houver uma tentativa de declaração da função somente leitura existente, você verá uma mensagem de erro. O último arquivo de origem antes dele deve conter a declaração que você procura.

Você pode precisar colocar isso no perfil do sistema. Lembre-se também de reverter as alterações depois de encontrar o culpado.

woodengod
fonte
-3

Você tentou isso?

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

ou qualquer um dos outros comandos encontrados aqui:

Como encontro todos os arquivos que contêm texto específico no Linux? | Estouro de pilha

Parece que preciso lhe dar mais explicações. Sua pergunta "" Portanto, se você executar o seguinte comando, ele deverá retornar todos os arquivos onde uma função bash estiver definida.

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

Programação BASH - Funções | Projeto de documentação do Linux

RadFox
fonte
1
As respostas apenas para links não são absolutamente incentivadas. Por favor, adicione alguma explicação.
heemayl