Choisir entre .bashrc, .profile, .bash_profile, etc.

Ceci est embarrassant, mais après de nombreuses années d'utilisation de systèmes POSIX à temps plein, j'ai encore du mal à déterminer si une personnalisation de shell devrait être dans .bashrc , .profile ou ailleurs. Sans parler de certains fichiers de configuration spécifiques au système OS tels que .pam_environment .

Oui, je sais comment rompre avec la documentation et apprendre quand chaque fichier est ou n'est pas chargé. Ce que je me demande, c'est si quelqu'un a mis en place des lignes directrices complètes sur la façon de décider quel fichier mettre un type de personnalisation donné.

TL; DR:

  • ~/.bash_profile doit être super simple et simplement charger .profile et .bashrc (dans cet ordre)

  • ~/.profile a les choses NOT spécifiquement liées à bash, telles que les variables d'environnement ( PATH et les amis)

  • ~/.bashrc a tout ce que vous voulez sur une ligne de commande interactive. Invite de commandes, variable EDITOR , alias bash pour mon usage

Quelques notes supplémentaires:

  • Tout ce qui devrait être disponible pour les applications graphiques OU à sh (ou bash invoqué comme sh ) DOIT être dans ~/.profile

  • ~/.bashrc ne doit pas afficher quoi que ce soit

  • Tout ce qui devrait être disponible uniquement pour les shells de connexion devrait aller dans ~/.profile

  • Assurez-vous que ~/.bash_login n'existe pas.

Au cours des dernières années, j'ai eu beaucoup de temps à perdre, alors j'ai fait des recherches pour un peu plus de 10 minutes seulement. Je ne sais pas si c'est la meilleure mise en page, mais ce n'est que celui qui fonctionne correctement dans presque tous les cas.

Les exigences:

  • ~/.profile doit être compatible avec n'importe quel / bin / sh – cela inclut bash, dash, ksh, quoi que ce soit qu'une distro pourrait choisir d'utiliser.

  • Les variables d'environnement doivent être placées dans un fichier lue par les deux connexions de la console (c.-à-d. Un shell de "connexion") et des connexions graphiques (c.-à-d. Les gestionnaires d'affichage comme GDM, LightDM ou LXDM).

  • Il est très peu important d'avoir à la fois ~/.profile et ~/.bash_profile . Si ce dernier manque, bash utilisera heureusement le premier, et toutes les lignes spécifiques à bash peuvent être gardées avec un chèque pour $BASH ou $BASH_VERSION .

  • La séparation entre *profile et *rc est que le premier est utilisé pour les shells 'login', et le dernier chaque fois que vous ouvrez une fenêtre de terminal. Cependant, bash dans le mode 'login' ne ~/.bashrc pas ~/.bashrc , donc ~/.profile doit le faire manuellement.

La configuration la plus simple serait:

  • Avoir un ~/.profile qui définit toutes les variables d'environnement (sauf les bash spécifiques), peut-être imprime une ligne ou deux, puis les sources ~/.bashrc si elles sont exécutées par bash, en respectant la syntaxe sh-compatible autrement.

     Export TZ = "Europe / Paris"
     Exporter EDITOR = "vim"
     Si ["$ BASH"];  puis
         .  ~ / .bashrc
     Fi
     Temps de disponibilité
    
  • Avoir un ~/.bashrc qui effectue une configuration spécifique à un shell, protégé par une vérification du mode interactif pour éviter de briser des choses comme sftp sur Debian (où bash est compilé avec l'option de charger ~/.bashrc même pour les shells non interactifs) :

     [[$ - == * i *]] ||  Retourner 0
    
     PS1 = '\ h \ w \ $'
    
     Start () {service sudo "$ 1" début;  }
    

Cependant, il y a aussi le problème que certaines commandes non interactives (p. Ex. ssh <host> ls ) ignorent ~/.profile , mais les variables d'environnement leur seraient très utiles.

  • Certaines distributions (p. Ex. Debian) compilent leur bash avec l'option de source ~/.bashrc pour ces connexions non interactives. Dans ce cas, j'ai trouvé utile de déplacer toutes les variables d'environnement (les lignes export ... ) vers un fichier séparé, ~/.environ , et de le ~/.environ à partir de .profile et .bashrc , avec un garde à éviter Le faire deux fois:

     si !  ["$ PREFIX"];  Alors # ou $ EDITEUR, ou $ TZ, ou ...
         .  ~ / .environ # généralement toute variable que .environ lui-même mettrait
     Fi
    
  • Malheureusement, pour d'autres distributions (p. Ex. Arch), je n'ai pas trouvé une très bonne solution. Une possibilité est d'utiliser le module PAM (activé par défaut) pam_env en mettant ce qui suit dans ~/.pam_environment :

     BASH_ENV =. /. Environ # pas une faute de frappe;  Il doit être un chemin, mais ~ ne fonctionnera pas
    

    Ensuite, bien sûr, mettre à jour ~/.environ pour unset BASH_ENV .


Conclusion? Les coquilles sont une douleur. Les variables environnementales sont une douleur. Les options de temps de compilation spécifiques à la distribution sont une immense douleur dans le cul.

Jetez un oeil à cette excellente publication de blog par ShreevatsaR . Voici un extrait, mais allez à la publication du blog, cela inclut une explication pour des termes comme "shell de connexion", un organigramme et une table similaire pour Zsh.

Pour Bash, ils fonctionnent comme suit. Lisez la colonne appropriée. Exécute A, puis B, puis C, etc. Le B1, B2, B3 signifie qu'il n'exécute que le premier des fichiers trouvés.

 +----------------+-----------+-----------+------+ | |Interactive|Interactive|Script| | |login |non-login | | +----------------+-----------+-----------+------+ |/etc/profile | A | | | +----------------+-----------+-----------+------+ |/etc/bash.bashrc| | A | | +----------------+-----------+-----------+------+ |~/.bashrc | | B | | +----------------+-----------+-----------+------+ |~/.bash_profile | B1 | | | +----------------+-----------+-----------+------+ |~/.bash_login | B2 | | | +----------------+-----------+-----------+------+ |~/.profile | B3 | | | +----------------+-----------+-----------+------+ |BASH_ENV | | | A | +----------------+-----------+-----------+------+ | | | | | +----------------+-----------+-----------+------+ | | | | | +----------------+-----------+-----------+------+ |~/.bash_logout | C | | | +----------------+-----------+-----------+------+ 

Je vous propose mes lignes directrices «complètes»:

  • Créez .bash_profile et .profile chargez .bashrc s'il existe, en utilisant par exemple [ -r $HOME/.bashrc ] && source $HOME/.bashrc
  • Placez tout le reste dans .bashrc .
  • Arrête de t'en faire.
  • Tous les quatre ans environ, passons dix minutes à la recherche de cette question même avant de renoncer et de revenir à "pas inquiétant".

EDIT: Ajouté des citations effrayantes à "complet" au cas où quelqu'un serait tenté de le croire. 😉

Placez tout dans .bashrc , puis source .bashrc depuis .profile

À partir de la page man bash (sur OS X 10.9):

Lorsqu'un shell interactif qui n'est pas un shell de connexion est démarré, bash lit et exécute des commandes de ~ / .bashrc, si ce fichier existe. Cela peut être inhibé en utilisant l'option –norc. L'option –rcfile file forçe bash à lire et à exécuter des commandes à partir du fichier au lieu de ~ / .bashrc

Le texte ci-dessus explique pourquoi tout est mis dans .bashrc . Cependant, il existe un comportement un peu différent lorsque vous rencontrez un shell de connexion. Encore une fois, citant la page man:

Lorsque bash est invoqué comme un shell de connexion interactif, ou comme un shell non interactif avec l'option –login, il lit et exécute les commandes à partir du fichier / etc / profile, si ce fichier existe. Après avoir lu ce fichier, il recherche ~ / .bash_profile, ~ / .bash_login et ~ / .profile, dans cet ordre, et lit et exécute les commandes du premier qui existe et est lisible. L'option –noprofile peut être utilisée lorsque le shell commence à inhiber ce comportement.

.profile est lu pour les shells de connexion, mais .bashrc n'est pas. La duplication de toutes ces choses dans .bashrc est mauvaise, donc nous devons la .profile dans .profile pour que le comportement reste cohérent.

Cependant, vous ne voulez pas .bashrc de .profile inconditionnellement. Consultez les commentaires et autres réponses pour plus de détails.

J'ai abandonné pour tenter de comprendre celui-ci et j'ai fait un script ( ~/.shell-setup ) que je source de tous les autres.

Cette approche nécessite ~/.shell-setup pour avoir deux fonctionnalités:

  1. N'utilisez qu'une seule fois, même si elle est générée à plusieurs reprises (utiliser Inclure les gardes )
  2. Ne génère pas de sortie indésirable (détecter lorsque la sortie est correcte)

# 1 est assez standard, bien que peut-être pas utilisé beaucoup dans les scripts shell.

# 2 est plus difficile. Voici ce que j'utilise en bash:

 if [ "" == "$BASH_EXECUTION_STRING" -a "" == "$DESKTOP_SESSION" ]; then echo "Hello user!" # ... etc fi 

Malheureusement, je ne me souviens pas de la façon dont je l'ai trouvé, ou pourquoi la détection d'une coque interactive n'était pas suffisante.