Découvrez quels scripts sont exécutés par bash au démarrage

15

Après avoir démarré un terminal bash, j'ai remarqué que la variable PATH contient des entrées en double. Mon terminal démarre un shell de connexion , il ~/.bash_profileest donc d' origine, suivi de ~/.profileet ~/.bashrc. Ce n'est qu'en ~/.profilecréant les entrées de chemins qui sont dupliquées.

Pour être pédant, c'est l'ordre dans lequel les fichiers qui DEVRAIENT être sourcés sont sourcés:

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

Avant que quiconque ne marque cela comme un doublon de "la variable PATH contient des doublons", continuez à lire.

Au début, je pensais que cela avait à voir avec le fait d' ~/.profileavoir été sourcé deux fois, j'ai donc dû écrire le fichier dans un fichier journal chaque fois qu'il était sourcé, et étonnamment, il n'a enregistré qu'une seule entrée, ce qui me dit qu'il n'a été sourcé qu'une seule fois. Encore plus surprenant est le fait que lorsque je commente les entrées qui étaient ~/.profile, les entrées apparaissent toujours dans la PATHvariable. Cela m'a conduit à trois conclusions, dont l'une a été rapidement écartée:

  1. Bash ignore les commentaires bash valides et exécute toujours le code commenté
  2. Il existe un script qui lit le ~/.profileet ignore tout code qui imprime une sortie (le fichier journal par exemple)
  3. Il y a une autre copie de mon ~/.profilequi est achetée ailleurs

Le premier, j'ai rapidement conclu que ce n'était pas le cas en raison de tests rapides. Les deuxième et troisième options sont celles où j'ai besoin d'aide.

Comment rassembler un journal des scripts qui sont exécutés au démarrage de mon terminal? J'ai utilisé echodans les fichiers que j'ai vérifiés pour savoir s'ils provenaient de bash, mais je dois trouver une méthode concluante qui retrace l'exécution jusqu'au moment où le terminal est prêt pour que je commence à taper dedans.

Si ce qui précède n'est pas possible, quelqu'un peut-il suggérer où je peux chercher pour voir quels scripts sont exécutés .


Référence future

Voici le script que j'utilise maintenant pour ajouter à mon chemin:

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
}

Je l'utilise comme ceci:

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

Le script vérifie si le chemin existe déjà dans la variable avant de l'ajouter.

Pour les utilisateurs de zsh, vous pouvez utiliser cet équivalent:

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
}

Modifier le 28/8/2018

Une autre chose que j'ai trouvé que je pouvais faire avec ce script est de corriger également le chemin. Donc au début de mon .bashrcdossier, je fais quelque chose comme ça:

_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

C'est à vous de décider par quoi PATHcommencer. Examinez d' PATHabord pour décider.

smac89
la source
Bash ne lit que ~/.profile si ~/.bash_profilen'existe pas ...
jasonwryan
@jasonwryan, je source ~/.profileet ~/.bashrcde~/.bash_profile
smac89

Réponses:

30

Si votre système en dispose, stracevous pouvez lister les fichiers ouverts par le shell, par exemple en utilisant

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

( -lisignifie shell de connexion interactif; à utiliser uniquement -ipour un shell interactif sans connexion.)

Cela affichera une liste de fichiers que le shell a ouvert ou essayé d'ouvrir. Sur mon système, ils sont les suivants:

  1. /etc/profile
  2. /etc/profile.d/*(divers scripts en /etc/profile.d/)
  3. /home/<username>/.bash_profile (cela échoue, je n'ai pas un tel fichier)
  4. /home/<username>/.bash_login (cela échoue, je n'ai pas un tel fichier)
  5. /home/<username>/.profile
  6. /home/<username>/.bashrc
  7. /home/<username>/.bash_history (historique des lignes de commande; ce n'est pas un script)
  8. /usr/share/bash-completion/bash_completion
  9. /etc/bash_completion.d/* (divers scripts fournissant une fonctionnalité de saisie semi-automatique)
  10. /etc/inputrc (définit les raccourcis clavier; ce n'est pas un script)

Utilisez man stracepour plus d'informations.

AlexP
la source
Merci pour votre contribution, mais je pense qu'il y a quelque chose de grave avec ma bash. Courir echo $0dans le terminal donne -bashplutôt que prévu bash. Avez-vous d'autres suggestions à ce sujet?
smac89
3
@ smac89: C'est normal pour un shell de connexion. Bash se comporte comme un shell de connexion lorsque le 1er caractère de $0est un tiret -, ou lorsqu'il est invoqué avec l'option -l.
AlexP
OK, c'est un peu un soulagement. J'ai exécuté la commande que vous avez donnée et la sortie semble vraiment compliquée, mais néanmoins tous les fichiers affichés ne contiennent pas les entrées dupliquées. Cela m'amène à penser que les entrées dupliquées se produisent lorsque je me connecte pour la première fois à mon compte, c'est-à-dire que quelque chose cherche initialement les entrées dans ce fichier et est-il recommencé lorsque j'ouvre le terminal? En fait, je pense que ça pourrait être ça. Lorsque je me connecte à mon compte, les entrées proviennent et, à nouveau, lorsque j'ouvre le terminal, le processus est répété. Est-ce que cela semble possible?
smac89
Pourquoi ne déboguez-vous pas à l'ancienne, en mettant echo PATH=\""$PATH"\"au début et à la fin de .profileet .bashrc? Et pourquoi ne faites-vous pas ce que tout le monde fait et définissez le PATH soit complètement, soit, si vous ajoutez un répertoire, gardez echo ":$PATH:" | grep -q ":/path/to/dir:" || export PATH="$PATH:/path/to/dir":?
AlexP
4
Utilisez sudo bash -c "echo exit|dtruss bash -li|& less|grep '^open'"sur macOS. (il suffit de remplacer stracepar dtruss)
Max Coplan