10 février 2017

bashrc vs bash_profile

Au démarrage de bash son comportement varie suivant qu’il sera avec ou sans login et qu’il sera interactif ou pas. Ce qui nous fait 4 cas à étudier.


   | Non interactif | Interactif |
-----------+----------------+------------|
Sans login |    #0     |    #1      |
-----------+----------------+------------|
Avec login |    #2          |    #3      |
-----------------------------------------+

Pour chaque cas nous allons nous intéressé
- Au fichier exécuté au démarrage  ( ~/.bashrc  ou ~/.bash_profile ou rien)
- A la variable $0 c’est-à-dire  le nom du shell  (avec ou sans - )
- A la variable $- qui donne les paramètres utilisés pour invoquer le shell
- A la variable $TERM
- A la variable $PS1, qui détermine le prompt du shell.

Important: on ne prend pas en compte le fait que sur beaucoup de distributions Linux ~/.bash_profile charge aussi ~/.bashrc.

Cas #3 : shell avec login et interactif.

Ce cas correspond au cas classique d'une connexion à une machine via ssh ou telnet ou directement via la console. Ou encore avec la commande 'su - user'.
Dans tous ces cas on obtient une shell interactif suite à une procédure de login. Il s'agit d'une ouverture de session.
Exécution de ~/.bash_profile$0 = -bash
$- = himBH
TERM=linux
$PS1 est définit

Cas #2 : shell avec login mais non interactif.

En dehors de quelques cas obscurs de l'environnement X le cas le plus classique est l’exécution sur une machine distante de commandes via un pipe avec ssh.
echo date | ssh serveur.exemple.com 
ssh serveur.exemple.com < script.sh
Le shell qui s’exécutera sur serveur.exemple.com sera avec login mais non interactif.
Exécution de ~/.bash_profile$0 = -bash
$- == hB
TERM = dumb
$PS1 n'est pas définit

Cas #1 : shell sans login et interactif

Typiquement cela arrive quand on lance bash depuis un autre shell, ou que l’on exécute screen ou la commande  'su user' ou encore quand on ouvre un terminal X.
Exécution de ~/.bashrc$0 = bash
$- = himBH
TERM = linux
$PS1 est définit
Dans le cas de la commande screen les choses sont un peu différentes :
Exécution de ~/.bashrc$0 = /bin/bash
$- == himBH
TERM = screen.linux
$PS1 est définit

Cas #0 : shell sans login et non interactif

Il s’agit d’un shell exécuté depuis un autre programme pour exécuter un script ou une commande.
C'est typiquement le cas quand on utilise ssh pour exécuter une commande sur une autre machine

ssh server.exemple.com date
Dans ce cas on a :
Exécution de ~/.bashrc
$0 = bash
$- = hBc
TERM = dumb
$PS1 non définit

L’exécution du shell peut aussi être aussi provoquée par un script shell, Perl, php etc…
Dans le cas d’un shell exécuté par Perl on a :
Pas de fichier exécuté
$0 = sh
$- == hBc
TERM = linux
$PS1 non définit
 ATTENTION : L’exécution de bash étant faite par un autre programme il est possible, en passant des paramètres à bash (comme --norc ou --noprofile ou --rcfile) de changer son comportement au démarrage. Donc à vérifier en fonction de qui exécute bash.
NOTE: cela ne concerne pas les  sub-shell qui sont en général utilisés pour exécuter des commandes entre parenthèses. Un sub-shell est un fork et est donc quasiment identique à son parent.  En particulier aucun fichier n’est chargé.

REMARQUES

~/.bash_profile est invoqué à l'ouverture d'une session (shell avec login).
~/.bashrc est invoqué quand la session est deja établie (shell sans login).

Quand $0 (le nom du shell) commence par le signe moins '-' le shell et en mode avec login.

Si $- contient la lettre minuscule 'i' c'est que le shell est en mode interactif.
De même, si $PS1 est définit c'est que l'on est en mode interactif.


Quoi mettre dans .bashrc et dans .bash_profile ?

Si vous avez suivi ce qui précède vous pouvez en conclure que pour un usage général d'un compte :

.bashrc ne doit rien afficher car il est exécuté à chaque invocation du shell par un autre programme. Il n’est pas question d’afficher la blague du jour et le nombre de mails non lu et la température du processeur à chaque fois !
.bashrc doit mettre en place l’environnement nécessaire aux taches programmables, automatisées, scriptables.

.bash_profile commence par exécuter .bashrc et complète pour obtenir une session de travail complète. 

Autrement dit : Faire en sorte que tout marche avec un minimum de chose dans .bashrc et un maximum dans .bash_profile.

Notez que le définition de "tout" varie d'un utilisateur à l'autre ;-)