Descubra quais scripts estão sendo executados pelo bash na inicialização

15

Depois de iniciar um terminal bash, notei que a variável PATH contém entradas duplicadas. Meu terminal inicia um shell de login , portanto, ~/.bash_profileé fornecido, seguido por ~/.profilee ~/.bashrc. Somente em ~/.profileque eu crio as entradas de caminhos duplicadas.

Para ser pedante, esta é a ordem na qual os arquivos que DEVEM ser adquiridos estão sendo adquiridos:

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

Antes que alguém marque isso como uma duplicata de "A variável PATH contém duplicatas", continue lendo.

No começo, pensei que isso tivesse a ver com ~/.profilea origem de duas vezes; portanto, o arquivo foi gravado em um arquivo de log sempre que foi originado e, surpreendentemente, ele registrou apenas uma entrada, o que me diz que foi originada apenas uma vez. Ainda mais surpreendente é o fato de que, quando eu comento as entradas que estavam ~/.profile, as entradas ainda aparecem na PATHvariável. Isso me levou a três conclusões, uma das quais foi rapidamente descartada:

  1. O Bash ignora comentários válidos do bash e ainda executa o código comentado
  2. Existe um script que lê ~/.profilee ignora qualquer código que imprima uma saída (o arquivo de log, por exemplo)
  3. Há outra cópia minha ~/.profileque está sendo adquirida em outro lugar

O primeiro, concluí rapidamente que não era o caso devido a alguns testes rápidos. A segunda e terceira opções são onde eu preciso de ajuda.

Como faço para reunir um log de scripts que são executados quando meu terminal é inicializado? Usei echonos arquivos que verifiquei para saber se eles são originados pelo bash, mas preciso encontrar um método conclusivo que rastreie a execução até o ponto em que o terminal estiver pronto para eu começar a digitar nele.

Se o exposto acima não for possível, alguém pode sugerir onde mais posso procurar para ver quais scripts estão sendo executados .


Referência futura

Este é o script que agora uso para adicionar ao meu caminho:

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
}

Eu uso assim:

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

O script verifica se o caminho já existe na variável antes de anexá-lo.

Para usuários zsh, você pode usar este equivalente:

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
}

Editar 28/8/2018

Mais uma coisa que descobri que poderia fazer com esse script é também corrigir o caminho. Então, no início do meu .bashrcarquivo, faço algo assim:

_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

Cabe a você o que PATHdeve começar. Examine PATHprimeiro para decidir.

smac89
fonte
Bash somente leituras ~/.profile se ~/.bash_profilenão existe ...
jasonwryan
@jasonwryan, I source ~/.profilee ~/.bashrcfrom~/.bash_profile
smac89 2/17

Respostas:

30

Se o seu sistema possuir strace, você poderá listar os arquivos abertos pelo shell, por exemplo, usando

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

( -lisignifica shell de logon interativo; use apenas -ipara um shell interativo sem logon.)

Isso mostrará uma lista de arquivos que o shell abriu ou tentou abrir. No meu sistema, eles são os seguintes:

  1. /etc/profile
  2. /etc/profile.d/*(vários scripts em /etc/profile.d/)
  3. /home/<username>/.bash_profile (isso falhar, não tenho esse arquivo)
  4. /home/<username>/.bash_login (isso falhar, não tenho esse arquivo)
  5. /home/<username>/.profile
  6. /home/<username>/.bashrc
  7. /home/<username>/.bash_history (histórico das linhas de comando; este não é um script)
  8. /usr/share/bash-completion/bash_completion
  9. /etc/bash_completion.d/* (vários scripts que fornecem a funcionalidade de preenchimento automático)
  10. /etc/inputrc (define ligações de teclas; isso não é um script)

Use man stracepara mais informações.

AlexP
fonte
Obrigado pela sua contribuição, mas acho que há algo seriamente errado com o meu bash. Correr echo $0no terminal dá -bashmais do que o esperado bash. Você tem outras sugestões para isso?
smac89
3
@ smac89: Isso é normal para um shell de login. Se comporta Bash como um shell de login quando o personagem 1º de $0é um traço -, ou quando chamado com a opção -l.
precisa saber é
OK, isso é um pouco de alívio. Eu executei o comando que você deu e a saída parece realmente complicada, mas, no entanto, todos os arquivos mostrados não contêm as entradas duplicadas. Isso está me levando a pensar que as entradas duplicadas acontecem quando eu primeiro faço login na minha conta, ou seja, algo está inicialmente procurando as entradas desse arquivo e é feito novamente quando eu abro o terminal? Na verdade, acho que pode ser isso. Quando entro na minha conta, as entradas são originadas e, novamente, quando abro o terminal, o processo é repetido. Isso parece possível?
smac89
Por que você não depura da maneira antiga, colocando echo PATH=\""$PATH"\"no início e no final de .profilee .bashrc? E por que você não faz o que todo mundo faz e define o PATH totalmente ou, se adicionar um diretório, guarda echo ":$PATH:" | grep -q ":/path/to/dir:" || export PATH="$PATH:/path/to/dir":?
precisa saber é
4
Use sudo bash -c "echo exit|dtruss bash -li|& less|grep '^open'"no macOS. (basta substituir stracecom dtruss)
Max Coplan