Choisir entre .bashrc, .profile, .bash_profile, etc. [dupliquer]

197

Cette question a déjà une réponse ici:

Ceci est gênant, mais après de nombreuses années d'utilisation des systèmes POSIX temps plein, il me reste encore du mal à comprendre si une personnalisation du shell devrait aller .bashrc, .profileou ailleurs. Sans parler de certains fichiers de configuration spécifiques au système d'exploitation, tels que .pam_environment.

Oui, je sais comment comprendre la documentation et savoir quand chaque fichier est chargé ou non. Ce que je me demande, c'est si quelqu'un a tous mis en place des directives complètes sur la manière de décider dans quel fichier mettre un type de personnalisation donné.

Avdi
la source
6
Cette question ne doit pas être marquée comme étant en double. La raison est que .profile n'est pas disponible dans la question ajoutée.
Premraj

Réponses:

222

TL; DR:

  • ~/.bash_profiledevrait être super-simple et juste charger .profileet .bashrc(dans cet ordre)

  • ~/.profilecontient des éléments non spécifiquement liés à bash, tels que des variables d'environnement ( PATHet des amis)

  • ~/.bashrca tout ce que vous voulez sur une ligne de commande interactive. Invite de commande, EDITORvariable, alias bash pour mon utilisation

Quelques autres notes:

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

  • ~/.bashrc ne doit rien sortir

  • Tout ce qui ne devrait être disponible que pour les coquilles de connexion devrait aller dans ~/.profile

  • Assurez-vous que cela ~/.bash_loginn'existe pas.

Dan Rabinowitz
la source
3
+1, cela permet ~/.profilede définir correctement l'environnement pour des services tels que GDM / LightDM / LXDM qui exécutent explicitement / bin / sh.
grawity
12
Mes .bashrcsorties beaucoup de choses, pouvez-vous commenter? En particulier, où devrais-je mettre le message d'accueil?
Calimo
14
@Calimo: Assurez-vous que la sortie produit en mode interactif. Vous pouvez le tester en utilisant [[ $- == *i* ]], c'est-à-dire en recherchant 'i' dans la $-variable spéciale . Bien sûr, cela n’a d’importance que sur les systèmes où bash est compilé pour être lu .bashrcen mode non interactif. (C'est, Debian mais pas Arch.) Mais il est une cause fréquente de mystérieux messages d'erreur lorsque vous tentez de vous connecter en utilisant sftpou scpou des outils similaires.
Grawity
4
Maintenant je dois savoir, pourquoi .bash_login n'existerait pas? Qu'est ce que ça fait?
tedder42
11
@ tedder42: Il fait la même chose que .bash_profileet .profile. Mais bash ne lit que le premier sur trois. Cela signifie que si vous en avez un .bash_login, les deux .profileet .bash_profileseront mystérieusement ignorés.
Grawity
54

Au cours des dernières années, j'ai eu beaucoup de temps à perdre et j'ai donc effectué des recherches pendant un peu plus de 10 minutes. Je n'ai aucune idée si c'est la meilleure mise en page, c'est juste une qui fonctionne correctement dans à peu près tous les cas.

Les exigences:

  • ~/.profile doit être compatible avec n’importe quel / bin / sh - cela inclut bash, dash, ksh, tout ce que la distribution pourrait choisir d’utiliser.

  • Les variables d'environnement doivent être placées dans un fichier lu à la fois par les connexions de la console (c'est-à-dire un shell 'login') et par des connexions graphiques (c'est-à-dire des gestionnaires d'affichage tels que GDM, LightDM ou LXDM).

  • Il y a très peu d'intérêt d'avoir les deux ~/.profile et ~/.bash_profile. Si ce dernier est manquant, bash l'utilisera avec plaisir, et toutes les lignes spécifiques à Bash peuvent être protégées par un contrôle de $BASHou $BASH_VERSION.

  • La séparation entre *profileet *rcconsiste en ce que le premier est utilisé pour les shells de «connexion», et le second à chaque fois que vous ouvrez une fenêtre de terminal. Cependant, bash en mode 'login' ne génère pas ~/.bashrc, il ~/.profilefaut donc le faire manuellement.

La configuration la plus simple serait:

  • Avoir un ~/.profileensemble qui définit toutes les variables d’environnement (à l’exception de celles spécifiques à bash), affiche éventuellement une ligne ou deux, puis les sources ~/.bashrcs’il est exécuté par bash, en respectant la syntaxe compatible sh.

    export TZ = "Europe / Paris"
    export EDITOR = "vim"
    si ["$ BASH"]; ensuite
        . ~ / .bashrc
    Fi
    la disponibilité
    
  • Ayez un programme ~/.bashrcqui exécute n'importe quelle configuration spécifique au shell, protégé avec une vérification du mode interactif pour éviter de casser des choses comme sftpsur Debian (où bash est compilé avec l'option de chargement ~/.bashrcmême pour les shells non interactifs):

    [[$ - == * i *]] || retourne 0
    
    PS1 = '\ h \ w \ $'
    
    start () {sudo service "$ 1" start; }
    

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

  • Certaines distributions (par exemple, Debian) compilent leur bash avec l’option de source ~/.bashrcpour de telles connexions non interactives. Dans ce cas, il m'a été utile de déplacer toutes les variables d'environnement (les export ...lignes) dans un fichier séparé ~/.environet de le générer à partir des deux .profile et .bashrc, avec une protection, pour éviter de le faire deux fois:

    si ! ["$ PREFIX"]; puis    # ou $ EDITOR, ou TZ $, ou ... 
        . ~ / .environ            # généralement toute variable définie par .environ elle-même
    Fi
    
  • Malheureusement, pour d'autres distributions (par exemple Arch), je n'ai pas trouvé de très bonne solution. Une possibilité consiste à utiliser le module PAM (activé par défaut) de pam_env, en mettant les éléments suivants dans ~/.pam_environment:

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

    Ensuite, bien sûr, mise ~/.environà jour vers unset BASH_ENV.


Conclusion? Les coquilles sont une douleur. Les variables d'environnement sont pénibles. Les options de compilation spécifiques à la distribution sont une immense douleur dans le cul.

Grawity
la source
2
+1 pour le dernier paragraphe, mais je préfère l' approvisionnement .profileet .bashrcde .bash_profileet de garder .profilepropre.
nyuszika7h
@ Nyuszika7h: Mon .profile est propre , merci.
Grawity
1
Notez que chaque fois que vous ouvrez une fenêtre, c’est l’inverse pour OSX
Mark
1
"Il y a très peu d'intérêt à avoir les deux ~/.profileet ~/.bash_profile": je suis en désaccord. Voir la réponse de Dan pour savoir pourquoi.
rubenvb
@rubenvb Pouvez-vous citer la partie pertinente? Je pense que c'est bien de n'avoir qu'un .profileet de garder les bashparties spécifiques avec des conditionnels.
Kelvin
36

Jetez un coup d'œil à cet excellent article de ShreevatsaR . Voici un extrait, mais consultez l'article du blog, qui inclut une explication de termes tels que "shell de connexion", un organigramme et un tableau similaire pour Zsh.

Pour Bash, ils fonctionnent comme suit. Lisez la colonne appropriée. Exécute A, puis B, puis C, etc. 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      |           |      |
+----------------+-----------+-----------+------+
Flimm
la source
C'est sympa. Il est important de noter que généralement, les /etc/profileappels /etc/bash.bashrcet les ~/.profileappels ~.bashrc. Tellement efficace, /etc/bash.bashrcet ~/.bashrcsont également exécutés pour les connexions interactives.
wisbucky
Notez que certaines distributions semblent outrepasser ce schéma (avec des conséquences étranges) - voir par exemple mon rapport de bogue à opensuse ici: bugzilla.opensuse.org/show_bug.cgi?id=1078124
Christian Herenz le
Btw. du moins avec bash, aucun de ces fichiers n’est exécuté lorsque la bash est appelée via/bin/sh
JepZ
@JepZ Vous avez raison, c'est ce que la troisième colonne "Script" explique.
Flimm le
1
@ Flimm Eh bien, la colonne 'Script' décrit ce qui se passe lorsque vous démarrez un script non interactif via bash (par exemple, / bin / bash). Cependant, si vous démarrez un script via sh (et / bin / sh est un lien symbolique vers / bin / bash), aucune des opérations ci-dessus n'est exécutée (même BASH_ENV). Le paragraphe correspondant de la page de manuel bash peut être trouvé en recherchant If bash is invoked with the name sh.
JepZ
21

Je vous propose mes directives "complètes":

  • Marque .bash_profileet .profilecharge .bashrcsi elle existe, en utilisant par exemple [ -r $HOME/.bashrc ] && source $HOME/.bashrc
  • Mettez tout le reste dans .bashrc.
  • Cesse de t'inquieter.
  • Tous les quatre ans environ, consacrez une dizaine de minutes à la recherche de cette question avant d'abandonner et de revenir à "ne vous inquiétez pas".

EDIT: Ajout de citations d'effarouchement à «complet» au cas où quelqu'un serait tenté de le croire. ;)

Poisson mécanique
la source
3
Avoir les deux .bash_profileet .profileest un peu redondant; vous avez seulement besoin de ce dernier. Vous devez cependant le rendre / bin / sh-proof, if [ "$BASH" ] && [ -r ~/.bashrc ]; then . ~/.bashrc; ficar il existe des programmes (notamment gdm / lightdm) qui extraient manuellement le fichier à partir d’un script / bin / sh. Cela signifie également que l’environnement conservé .bashrcserait inefficace. Dû à -1, car vos directives "complètes" ne fonctionneront pas sur beaucoup de systèmes, comme je l'avais découvert à plusieurs reprises.
Grawity
Pas de problème, je paierais volontiers un -1 pour une réponse qui n'est pas simplement "insipide", et vous avez certainement mérité ce titre.
Poisson mécanique
0

J'ai renoncé à essayer de comprendre celui-ci et ~/.shell-setupj'ai créé un script ( ) que je tire de tous les autres.

Cette approche nécessite ~/.shell-setupdeux fonctionnalités:

  1. N'exécutez qu'une seule fois, même si les sources sont utilisées à plusieurs reprises (utilisez les protections Inclure )
  2. Ne générez aucune sortie indésirable (détectez quand la sortie est correcte)

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

# 2 est plus compliqué. Voici ce que j'utilise dans bash:

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

Malheureusement, je ne me souviens pas comment je suis arrivé à cela, ni pourquoi la détection d'un shell interactif n'était pas suffisante.

ShadSterling
la source
-2

Tout mettre dans .bashrcpuis source .bashrcde.profile

Depuis la page de manuel de bash (sous OS X 10.9):

Lorsqu'un shell interactif qui n'est pas un shell de connexion est démarré, bash lit et exécute les commandes de ~ / .bashrc, si ce fichier existe. Cela peut être inhibé en utilisant l'option --norc. L'option de fichier --rcfile forcera bash à lire et à exécuter les commandes depuis le fichier au lieu de ~ / .bashrc

Le texte ci-dessus est la raison pour laquelle tout est mis en .bashrcpo Cependant, le comportement d'un shell de connexion est légèrement différent. Encore une fois, citant la page de manuel:

Lorsque bash est appelé en tant que shell de connexion interactif ou en tant que shell non interactif avec l'option --login, il commence par lire et exécuter les commandes 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, puis lit et exécute les commandes à partir de la première qui existe et est lisible. L'option --noprofile peut être utilisée au démarrage du shell pour empêcher ce comportement.

.profileest lu pour les coquilles de connexion, mais .bashrcn'est pas. La duplication de tout ce que cela contient .bashrcest mauvaise ™, nous devons donc le rechercher .profileafin que le comportement reste cohérent.

Cependant, vous ne voulez pas la source .bashrcde .profilemanière inconditionnelle. Veuillez consulter les commentaires et autres réponses pour plus de détails.

mattr-
la source
4
-1, ne pas source .bashrcde .profile. Voir la réponse de @ DanRabinowitz.
Nyuszika7h
Du moins pas inconditionnellement.
nyuszika7h
[ -n "$BASH" -a -f ~/.bashrc ] && . ~/.bashrcserait un doux oneliner pour .profile.
John WH Smith
@ nyuszika7h, pourquoi pas? Tout le monde semble suggérer de le faire.
Pacerier