Scopri quali script vengono eseguiti da bash all'avvio


15

Dopo aver avviato un terminale bash, ho notato che la variabile PATH contiene voci duplicate. Il mio terminale avvia una shell di login , quindi ~/.bash_profileè di provenienza, seguito da ~/.profilee ~/.bashrc. Solo in ~/.profilefaccio creo le voci dei percorsi che sono duplicate.

Per essere pedanti, questo è l'ordine in cui i file che DOVREBBERO essere approvati vengono acquistati:

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

Prima che qualcuno lo contrassegni come duplicato di "La variabile PATH contiene duplicati", continua a leggere.

Inizialmente pensavo che questo avesse a che fare con la ~/.profileprovenienza due volte, quindi ho dovuto scrivere il file in un file di registro ogni volta che era di provenienza, e sorprendentemente ha registrato solo una voce, il che mi dice che è stata fornita una sola volta. Ancora più sorprendente è il fatto che quando commento le voci che erano in ~/.profile, le voci appaiono ancora nella PATHvariabile. Ciò mi ha portato a tre conclusioni, una delle quali è stata rapidamente esclusa:

  1. Bash ignora i commenti bash validi ed esegue comunque il codice commentato
  2. Esiste uno script che legge ~/.profilee ignora qualsiasi codice che stampa un output (ad esempio il file di registro)
  3. C'è un'altra mia copia ~/.profileche viene acquistata altrove

Il primo, ho rapidamente concluso di non essere il caso a causa di alcuni test rapidi. La seconda e la terza opzione sono quelle in cui ho bisogno di aiuto.

Come faccio a raccogliere un registro di script che vengono eseguiti all'avvio del mio terminale? Ho usato echonei file che ho controllato per sapere se sono stati originati da bash, ma ho bisogno di trovare un metodo conclusivo che traccia l'esecuzione fino al punto in cui il terminale è pronto per iniziare a digitare.

Se quanto sopra non è possibile, allora qualcuno può suggerire dove altro posso guardare per vedere quali script sono in esecuzione .


Referenza futura

Questo è lo script che ora uso per aggiungere al mio percorso:

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
}

Lo uso così:

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

Lo script verifica se il percorso esiste già nella variabile prima di anteporlo.

Per gli utenti di zsh, puoi usare questo 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
}

Modifica il 28/8/2018

Un'altra cosa che ho scoperto di poter fare con questo script è anche quella di correggere il percorso. Quindi all'inizio del mio .bashrcfile, faccio qualcosa del genere:

_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

Dipende da te cosa PATHdovrebbe iniziare. Esaminare PATHprima per decidere.


Bash legge solo ~/.profile se ~/.bash_profilenon esiste ...
Jasonwryan,

@jasonwryan, fonte ~/.profilee ~/.bashrcda~/.bash_profile
smac89

Risposte:


30

Se il tuo sistema lo ha strace, puoi elencare i file aperti dalla shell, ad esempio usando

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

( -liindica la shell di accesso interattiva; utilizzare solo -iper una shell di accesso non interattiva.)

Questo mostrerà un elenco di file che la shell ha aperto o provato ad aprire. Sul mio sistema, sono i seguenti:

  1. /etc/profile
  2. /etc/profile.d/*(vari script in /etc/profile.d/)
  3. /home/<username>/.bash_profile (questo non riesce, non ho tale file)
  4. /home/<username>/.bash_login (questo non riesce, non ho tale file)
  5. /home/<username>/.profile
  6. /home/<username>/.bashrc
  7. /home/<username>/.bash_history (cronologia delle righe di comando; questo non è uno script)
  8. /usr/share/bash-completion/bash_completion
  9. /etc/bash_completion.d/* (vari script che forniscono funzionalità di completamento automatico)
  10. /etc/inputrc (definisce i collegamenti chiave; questo non è uno script)

Utilizzare man straceper ulteriori informazioni.


Grazie per il tuo contributo, ma penso che ci sia qualcosa di gravemente sbagliato nel mio bash. L'esecuzione echo $0nel terminale dà -bashpiuttosto che il previsto bash. Hai altri suggerimenti per questo?
smac89,

3
@ smac89: è normale per una shell di accesso. Bash si comporta come una shell di login quando il primo carattere di $0è un trattino -o quando viene invocato con l'opzione -l.
AlexP

OK è un po 'di sollievo. Ho eseguito il comando che hai dato e l'output sembra davvero complicato, ma comunque tutti i file mostrati non contengono le voci duplicate. Questo mi sta portando a pensare che le voci duplicate si verificano quando accedo per la prima volta al mio account, ovvero qualcosa sta inizialmente acquistando le voci in quel file e viene fatto di nuovo quando apro il terminale? In realtà penso che potrebbe essere. Quando accedo al mio account, le voci provengono e di nuovo quando apro il terminale il processo si ripete. Sembra possibile?
smac89,

Perché non eseguire il debug alla vecchia maniera, mettendo echo PATH=\""$PATH"\"all'inizio e alla fine di .profilee .bashrc? E perché non si fa quello che fanno tutti e impostare sia pienamente il PATH, o, se l'aggiunta di una directory, custodito: echo ":$PATH:" | grep -q ":/path/to/dir:" || export PATH="$PATH:/path/to/dir"?
AlexP

4
Usa sudo bash -c "echo exit|dtruss bash -li|& less|grep '^open'"su macOS. (basta sostituire stracecon dtruss)
Max Coplan
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.