J'exécute une nouvelle installation Oneiric (c'est-à-dire pas une mise à niveau) sur deux systèmes différents et rencontre le même ensemble de problèmes apparemment liés.
Le plus frustrant du groupe est que, lorsque j'utilise le .profile et .bashrc que j'ai emporté avec moi depuis Mac OS X, la connexion à X via LightDM me déconnecte immédiatement. Je crois que cela est dû au fait que, lors de l'exécution de "/ bin / sh", il se comporte comme / bin / dash, mais a toujours la variable $ SHELL définie sur / bin / bash.
Extrapolation
J'en ai un énorme .bashrc
. Vous pouvez le voir ici si vous le souhaitez, mais son contenu n'est probablement pas pertinent, à part le fait qu'il est plein de bashismes et le fait qu'il fonctionne sans erreur à l'intérieur de xterm ou sur une console virtuelle.
Mon .profile
ressemble à ceci (abrégé):
case $SHELL in
*bash*)
if [ -f $HOME/.bashrc -a -r $HOME/.bashrc ]; then
. $HOME/.bashrc
fi
;;
esac
Si j'essaie de me connecter à X via LightDM, cela me déconnectera immédiatement. Je reçois des erreurs .xsession-errors
concernant mon .bashrc qui ressemblent à ceci (en abrégé):
/home/mrled/.bashrc: 103: [[: not found
[: 103: Linux: unexpected operator
[: 274: -P :: unexpected operator
/home/mrled/.bashrc: 520: complete: not found
Comme je l'ai dit, lorsque j'exécute bash à partir d'une console virtuelle, je n'obtiens pas ces erreurs. De plus, si je supprime mon .profile, je peux très bien me connecter à X. (Je peux également me connecter à une console virtuelle et l'utiliser startx
pour lancer une session X qui fonctionne, mais ce n'est bien sûr pas une solution à long terme.)
Cependant, j'ai découvert que si je cours /bin/sh -l
, je ne reçois les erreurs. Voici un exemple de session (remarque: l'invite bash que j'ai simplifiée bash>
et l'invite sh est juste $
):
bash> echo $SHELL
/bin/bash
bash> echo $BASH_VERSION
4.2.10(1)-release
bash> /bin/sh -l
/home/mrled/.bashrc: 103: [[: not found
[: 103: Linux: unexpected operator
[: 274: -P :: unexpected operator
/home/mrled/.bashrc: 520: complete: not found
$ echo $SHELL
/bin/bash
$ echo $BASH_VERSION
$
Q1: Pourquoi cela se produit-il?
Je comprends que / bin / sh pointe maintenant vers un tiret plutôt que vers bash , mais si c'est vrai, alors pourquoi revient-il $SHELL
encore /bin/bash
?
Q2: Que puis-je faire pour contourner ce problème?
Y a-t-il un moyen de contourner cela? Je veux garder mon profil en charge .bashrc afin que j'obtienne le même environnement sur les shells de connexion et non-login, mais évidemment je veux seulement qu'il se charge pour bash lui-même, pas / bin / sh se faisant passer pour bash.
Vous avez peut-être remarqué la différence dans le contenu des variables $ BASH_VERSION ci-dessus. J'ai essayé d'envelopper mon .profile dans quelque chose comme ceci:
if [ -n $BASH_VERSION ]; then
# the rest of my .profile as above
fi
Le -n
test ne doit renvoyer true que si la longueur de la chaîne n'est pas nulle, cependant, même si dans la session ci-dessus, lorsque je cours sous, /bin/sh -l
il retourne une chaîne vide pour $ BASH_VERSION, lorsqu'elle est incluse dans mon .profile comme ceci , ça passe le test! Il les procède à la source de mon .bashrc et me donne les mêmes erreurs qu'auparavant.
Maintenant, je suis vraiment confus.
la source
dash -l
montre également$SHELL
avoir la valeur/bin/bash
.$SHELL
est tout ce que le dernier champ de/etc/passwd
(ougetent passwd
) dit.~/.profile
bash, des choses spécifiques à bash~/.bashrc
et avoir la~/.bash_profile
source à la fois.Réponses:
Vous pouvez faire en sorte que le fait qui
$BASH_VERSION
soit viergedash
vous corresponde:la source
if [ "$BASH_VERSION" = '' ]
-n
simplement , ou rien . (+1, cependant.= ''
Fonctionne parfaitement bien.)Il vous suffit d'utiliser des guillemets sur la variable
BASH_VERSION
à utiliser-n
la source
[ "$EMPTY_STRING" ]
évalue faux, vous n'avez même pas besoin de-n
. Il suffit de citer la variable.Utilisez
/proc/[PID]/cmdline
pour voir avec quoi le script est exécuté et tester ce qu'il contient. La$$
variable nous donnera le PID du shell en cours d'exécution. Ainsi, nous pouvons faire un script comme celui-ci,Voici un test du même script:
la source
bash
son nom; il n'est pas rare que l'bash
exécutable soit exécuté via un lien symbolique avec un autre nom. Habituellement, on voudrait toujours considérer ce Bash. En outre, le modèle est mis en correspondance n'importe où dans/proc/$$/cmdline
, ce qui devrait être possible de corriger, mais gardez à l'esprit que les argumentscmdline
sont délimités par des caractères nuls.grep -qE '(^|/)bash$'
se sent comme si cela devrait fonctionner mais donne un faux positif quand un argument estbash
.