Réponses:
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.)
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 soit yash
également défini PS1
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é!
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).
Un shell interactif définit la variable shellPS1
sur la chaîne d'invite par défaut. Donc, si le shell est interactif, il PS1
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 ne bash -c '… do stuff with $var…'
fonctionne pas quand var
est PS1
?). 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 utilisent PS1
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, le PS1
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.
.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 est rshd
ou sshd
). Dans ce deuxième cas, il est peu probable que PS1
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.
Il existe un moyen simple et portable de tester si le shell actuel est interactif: testez si l'option -i
est activée.
case $- in
*i*) echo "This shell is interactive";;
*) echo "This shell is not interactive";;
esac
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.
if [[ $- != *i* && -r ~/.profile ]]; then . ~/.profile; fi
[[ -o interactive ]]
(ksh, bash, zsh) ou case $- 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 que PS1=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").
$-
contient i
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 que Bourne Shell
clone.
Par conséquent, le comportement interactif POSIX ( $ENV
appelé pour les shells interactifs) a été ajouté ultérieurement bash
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:
$prompt not set non-interactive shell, test $?prompt.
$prompt set but == "" .cshrc called by the which(1) command.
$prompt set and != "" normal interactive shell.
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:
$ENV
qui a un nom spécifique au shell. C'est par exemple
$HOME/.kshrc for the korn shell
$HOME/.bashrc for bash
$HOME/.mkshrc for mksh
$HOME/.shrc for the POSIX Bourne Shell
D'autres personnes ont mentionné le drapeau shell -i
, mais ce n'est pas utilisable pour une programmation fiable. POSIX n'exige pas que cela set -i
fonctionne, ni qu'il $-
contienne un i
pour les shells interactifs. POSIX requiert simplement que sh -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 que bash
unset
s PS1
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
.
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,
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):
if [ "${PS1-}" ]; then
if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then
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:
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
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 $-
):
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
Cela devrait montrer clairement pourquoi la PS1 et une alternative.
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 :
# ~/.profile: executed by the command interpreter for login shells
# if running bash
if [ -n "$BASH_VERSION" ]; then
# include .bashrc if it exists
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi
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.
( 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.