À quoi sert l' [ -n "$PS1" ]
in dans [ -n "$PS1" ] && source ~/.bash_profile;
? Cette ligne est incluse dans un repo.bashrc
d'un fichier dot .
10
Ceci vérifie si le shell est interactif ou non. Dans ce cas, ne rechercher le ~/.bash_profile
fichier que si le shell est interactif.
Voir "Est-ce que Shell est interactif?" dans le manuel bash, qui cite cet idiome spécifique. (Il recommande également de vérifier si le shell est interactif en testant si la $-
variable spéciale contient le i
caractère, ce qui est une meilleure approche de ce problème.)
( export PS1='abc$ '; bash -c 'echo "[$PS1]"' )
, qui s'imprime simplement[]
. Il semble que zsh ne fasse pas de même, du moins à partir d'une expérience ... En tout cas, l' intention de la[ -n "$PS1" ]
est de vérifier si le shell est interactif ou non.bash
désactive PS1 lorsque non interactif (faute de frappe dans votre commentaire précédent) est un bug IMO, PS1 n'est pas une variable spécifique à bash, il n'a aucun intérêt à le désinstaller. C'est le seul shell qui le fait (bien qu'il soityash
également définiPS1
sur une valeur par défaut même lorsqu'il n'est pas interactif).[[ $- = *i* ]] && source ~/.bash_profile
).[ -n "${PS1}" ]
, mais j'ai toujours mis à jour ma réponse pour souligner que le manuel bash suggère / recommande également une inspection$-
pour déterminer si le shell est interactif, j'espère que vous trouverez que cela améliore la réponse. À votre santé!Qu'est-ce que cela fait
Il s'agit d'un moyen répandu de tester si le shell est interactif. Attention, cela ne fonctionne qu'en bash, cela ne fonctionne pas avec d'autres shells. Donc, c'est ok (si idiot) pour
.bashrc
, mais cela ne fonctionnerait pas dans.profile
(qui est lu par sh, et bash n'est qu'une des implémentations possibles de sh, et pas la plus courante).Pourquoi ça marche (en bash seulement!)
Un shell interactif définit la variable shell
PS1
sur la chaîne d'invite par défaut. Donc, si le shell est interactif, ilPS1
est défini (à moins que l'utilisateur ne l'.bashrc
ait supprimé, ce qui ne peut pas encore se produire au sommet de.bashrc
, et vous pourriez considérer que c'est une chose idiote à faire de toute façon).L'inverse est vrai dans bash: les instances non interactives de bash ne sont pas définies
PS1
au démarrage. Notez que ce comportement est spécifique à bash, et est sans doute un bug (pourquoi nebash -c '… do stuff with $var…'
fonctionne pas quandvar
estPS1
?). Mais toutes les versions de bash jusqu'à 4.4 (y compris la dernière version que j'écris) le font.De nombreux systèmes exportent
PS1
vers l'environnement. C'est une mauvaise idée, car de nombreux shells différents utilisentPS1
mais avec une syntaxe différente (par exemple , les échappements d'invite de bash sont complètement différents des échappements d'invite de zsh ). Mais il est suffisamment répandu pour que dans la pratique, lePS1
fait de le définir ne soit pas un indicateur fiable que le shell est interactif. Le shell peut avoir héritéPS1
de l'environnement.Pourquoi il est (mal) utilisé ici
.bashrc
est le fichier que bash lit au démarrage lorsqu'il est interactif. Un fait moins connu est que bash lit également.bashrc
un shell de connexion et l'heuristique de bash conclut qu'il s'agit d'une session distante (bash vérifie si son parent estrshd
ousshd
). Dans ce deuxième cas, il est peu probable quePS1
cela soit défini dans l'environnement, car aucun fichier point n'a encore été exécuté.Cependant, la façon dont le code utilise ces informations est contre-productive.
.bash_profile
dans ce shell. Mais.bash_profile
c'est un script au moment de la connexion. Il peut exécuter certains programmes destinés à être exécutés une seule fois par session. Il peut remplacer certaines variables d'environnement que l'utilisateur a délibérément définies sur une valeur différente avant d'exécuter ce shell. L'exécution.bash_profile
dans un shell sans connexion est perturbatrice..bash_profile
. Mais c'est le cas où le chargement.bash_profile
pourrait être utile, car un shell de connexion non interactif ne se charge pas automatiquement/etc/profile
et~/.profile
.Je pense que la raison pour laquelle les gens font cela est pour les utilisateurs qui se connectent via une interface graphique (un cas très courant) et qui mettent leurs paramètres de variable d'environnement
.bash_profile
plutôt que.profile
. La plupart des mécanismes de connexion à l'interface graphique invoquent.profile
mais pas.bash_profile
(la lecture.bash_profile
nécessiterait l'exécution de bash dans le cadre du démarrage de la session, au lieu de sh). Avec cette configuration, lorsque l'utilisateur ouvre un terminal, il obtient ses variables d'environnement. Cependant, l'utilisateur n'obtiendra pas ses variables d'environnement dans les applications GUI, ce qui est une source de confusion très courante. La solution ici consiste à utiliser.profile
au lieu de.bash_profile
définir des variables d'environnement. L'ajout d'un pont entre.bashrc
et.bash_profile
crée plus de problèmes qu'il n'en résout.Que faire à la place
Il existe un moyen simple et portable de tester si le shell actuel est interactif: testez si l'option
-i
est activée.Ceci est utile
.bashrc
pour lire.profile
uniquement si le shell n'est pas interactif - c'est -à -dire l'opposé de ce que fait le code! Lisez.profile
si bash est un shell de connexion (non interactif) et ne le lisez pas s'il s'agit d'un shell interactif.la source
[[ -o interactive ]]
(ksh, bash, zsh) oucase $- in (*i*) ...; esac
(POSIX)PS1
s'il n'est pas exécuté de manière interactive. Il est assez facile à tester:PS1=cuckoo bash -c '[ -n "${PS1}" ] && echo "PS1=[${PS1}]"'
n'imprimera rien, tandis quePS1=cuckoo bash -i -c '[ -n "${PS1}" ] && echo "PS1=[${PS1}]"'
la valeur$PS1
définie dans vos fichiers de démarrage bash sera imprimée (il n'imprimera pas la chaîne "coucou").$-
contienti
avec un shell interactif.[ -n "${PS1}" ]
mal appeler va un peu trop loin, après tout, cela ne casse que lorsque quelqu'un exporte PS1 (ce qui dans votre réponse vous dit que c'est une mauvaise idée et même expliquer les raisons) et cela n'affecte pas bash de toute façon (car il désactive PS1 et PS2 si le shell n'est pas interactif.) Peut-être aurait-il été préférable d'utiliser un mot tel que "découragé" ou de parler des "limites" de l'approche. Je ne pense pas que ce soit "faux" tout à fait. Si quelque chose ne va pas lors de l' exportation de PS1, c'est sûr! Quoi qu'il en soit, merci d'être entré dans les détails de cela.Il semble que ce concept étrange résulte du fait qu'il
bash
n'a pas commencé en tant que clone shell POSIX mais en tant queBourne Shell
clone.Par conséquent, le comportement interactif POSIX (
$ENV
appelé pour les shells interactifs) a été ajouté ultérieurementbash
et n'est pas largement connu.Il existe un shell qui accorde un comportement similaire. Il s'agit des
csh
subventions csh qui$prompt
ont des valeurs spécifiques:Mais cela ne s'applique ni au Bourne Shell ni aux shells POSIX.
Pour un shell POSIX, la seule méthode autorisée consiste à mettre du code pour les shells interactifs dans le fichier:
qui a un nom spécifique au shell. C'est par exemple
D'autres personnes ont mentionné le drapeau shell
-i
, mais ce n'est pas utilisable pour une programmation fiable. POSIX n'exige pas que celaset -i
fonctionne, ni qu'il$-
contienne uni
pour les shells interactifs. POSIX requiert simplement quesh -i
le shell soit appliqué en mode interactif.Comme la variable
$PS1
peut être importée de l'environnement, elle peut avoir une valeur même en mode non interactif. Le fait quebash
unset
sPS1
dans tout shell non interactif ne soit pas accordé par la norme et ne soit effectué par aucun autre shell.Une programmation si propre (même avec
bash
) consiste à placer les commandes des shells interactifs dans$HOME/.bashrc
.la source
Je vais d'abord parler de ce que Debian, et la plupart du temps aussi Ubuntu définit pour bash. Et ce dernier touche à d'autres systèmes.
Dans le cadre des fichiers de démarrage du shell, il y a beaucoup d'opinion.
J'ai également mon opinion mais je vais essayer de montrer des exemples existants de paramètres corrects.
J'utiliserai debuan car il est assez facile de trouver des exemples de ses fichiers.
Et debian est très utilisé, donc les paramètres ont été bien testés,
Quel est l'objectif de vérifier que la PS1 est définie?
Seulement pour savoir si le shell est interactif.
La valeur
/etc/profile
par défaut dans debian et ubuntu (depuis / usr / share / base-files / profile):L'if est lu: s'il est interactif (ensemble par défaut PS1) et qu'il s'agit d'un shell bash (mais n'agissant pas par défaut
sh
), changez PS1 en un nouveau particulier (pas celui par défaut).La valeur
/etc/bash.bashrc
par défaut dans debian contient également:Ce qui est assez clair dans ce qu'il fait: si interactif ne source pas (le reste).
Cependant, dans
/etc/skel/.bashrc
est un exemple de la bonne façon de tester un shell interactif (en utilisant$-
):Cela devrait montrer clairement pourquoi la PS1 et une alternative.
L'ordre correct
Le paramètre que vous signalez doit être évité.
L'ordre ( à partir des paramètres du système aux paramètres utilisateur plus spécifiques (pour bash)) est
/etc/profile
,/etc/bash.bashrc
,~/.profile
et enfin~/.bashrc
. Cela place les effets les plus larges (et pour plus de shells) dans/etc/profile
(qui appartient à root) suivi par/etc/bash.bashrc
(qui appartient également à root) mais n'affecte que bash. Ensuite viennent les paramètres personnels$HOME
, le premier est~/.profile
pour la plupart des shells et~/.bashrc
(presque équivalent à~/.bash_profile
), spécifique pour bash uniquement.Il est donc erroné de la source
~/.bashrc
dans~/.profile
, il est en train de transformer un utilisateur spécifique pour la mise en bash à un plus général qui touche de plus coquilles . Sauf si cela se fait de cette manière :Il vérifie que bash est en cours d'exécution et ne se charge
.bashrc
que si c'est le cas.Il s'agit d'une décision en amont venant de Debian. La justification est expliquée ici .
En fait, l'inverse, l'approvisionnement
~/.profile
en~/.bash_profile
(ou~/.bashrc
) ne fait que réappliquer des règles générales qui auraient déjà dû être chargées dans un cas d'utilisation particulier, et donc "pas si mal" (je ne dis pas "bien"). Et je ne dis pas bien car cela peut provoquer une boucle de sourcing des fichiers. Comme lorsqu'un sous-répertoire charge un parent, c'est une boucle de répertoire.Et c'est dans ce cross sourcing que le contrôle du shell interactif est logique. Ce n'est que lorsqu'un shell interactif est
~/.bashrc
chargé, mais il peut à son tour se charger~/.profile
(ou l'inverse) et c'est dans ce cas que la recherche d'un shell interactif peut être utilisée.la source