Où est défini le shell de connexion?

16

Je lisais la différence entre sudo -i/-s ici . Après avoir utilisé la commande, shoptil est à noter que tous ( sudo su/sudo -i/sudo -s) $SHELLfournissent les mêmes résultats, mais les shoptrésultats de la commande sont différents.

Alors, comment le shell de connexion et non de connexion est-il défini?

D'où shoptobtenir le résultat?

Pourquoi ce n'est pas lié à $SHELL?

sudo su

givinv@87-109:~$ sudo su
root@87-109:/home/givinv# 
root@87-109:/home/givinv# 
root@87-109:/home/givinv# shopt -q login_shell && echo 'Login shell' || echo 'No login shell'
No login shell
root@87-109:/home/givinv# echo $SHELL
/bin/bash
root@87-109:/home/givinv# 
root@87-109:/home/givinv# exit
givinv@87-109:~$ 

sudo -i

givinv@87-109:~$ sudo -i
root@87-109:~# 
root@87-109:~# shopt -q login_shell && echo 'Login shell' || echo 'No login shell'
Login shell
root@87-109:~# echo $SHELL
/bin/bash
root@87-109:~# 

sudo -s

root@87-109:~# sudo -s
root@87-109:~# shopt -q login_shell && echo 'Login shell' || echo 'No login shell'
No login shell
root@87-109:~# echo $SHELL
/bin/bash
root@87-109:~# 
prado
la source
7
Un problème est que "shell de connexion" a deux significations: 1. Il s'agit d'une instance d'un shell démarré d'une manière spécifique qui fait des choses spécifiques (comme la lecture .profileou des équivalents), et 2. C'est le shell qui est censé démarrer à la connexion pour un utilisateur, tel que défini dans /etc/passwdou équivalent. $SHELLcontient le dernier, vos shoptsorties concernent le premier. En règle générale, lorsque le shell dans (2) est démarré à la connexion, il est démarré de la manière spécifique requise pour (1), d'où la fusion des significations.
muru
1
L'explication de @muru est bonne. par exemple, si vous vous connectez à votre ordinateur depuis un ordinateur distant. / usr / sbin / sshd sur votre système bifurquerait un shell défini par $SHELL(et le connecterait à un pseudo terminal) qui à son tour est défini dans votre entrée / etc / passwd. ce shell est un shell de connexion et peut être testé avec if [[ -o login ]]; then echo "I am a login shell"; fi. étant un shell de connexion, il effectuerait les tâches appropriées à une nouvelle session. par exemple source ~/.zprofileou similaire qui pourrait éventuellement définir des variables d'environnement et tout code shell personnalisé que vous voudrez peut-être exécuter à ce moment
the_velour_fog

Réponses:

17

TL; DR :

  • Où est défini le shell de connexion? Dans /etc/passwd.
  • Sont sudo su/ sudo su -/ sudo -i/ sudo -sidentiques? Non, ils engendrent tous une coquille mais différemment et dans des contextes différents.
  • Que fait $SHELL-il? Indiquez simplement votre shell par défaut, comme dans /etc/passwd.

Réponse réelle :

Tout d'abord, il est important de mentionner que shoptc'est spécifique à bash. Par exemple, je suis mkshun utilisateur shell, et il n'en a pas shopt, tout comme kshne le fait pas.

Ensuite, qu'est-ce qui login_shellest censé représenter exactement ? De man bash:

login_shell

Le shell définit cette option s'il est démarré en tant que shell de connexion

Voilà le point clé. sudo -i, comme vous le savez déjà dans la réponse précédente que vous lisez, est censé simuler la connexion initiale. C'est pourquoi les shoptrapports login_shell on pour cette option. Considérez ceci comme si sudo -iforce le shell à parcourir les fichiers qui ne devraient apparaître que pendant un processus de connexion (qui ne sont pas fournis par des shells interactifs).

Dans d'autres cas, vous exécutez déjà une instance d'un shell, il ne peut donc pas s'agir d'un shell de connexion en premier lieu, et le but des options est différent. sudo -slit simplement $SHELL(qui est censée représenter votre shell par défaut tel que défini dans /etc/passwd) et l'exécute avec le privilège root. Cela équivaut à faire sudo $SHELLou sudo mkshou sudo bash(selon ce que vous utilisez).

Rappelez-vous que j'ai mentionné que je suis mkshutilisateur? Regarde ça:

$ bash --posix
bash-4.3$ sudo -s
[sudo] password for xieerqi: 

DIR:/xieerqi|01:53|skolodya@ubuntu:
$ id 
uid=0(root) gid=0(root) groups=0(root)

DIR:/xieerqi|01:53|skolodya@ubuntu:
$ echo $-
imsU

Ce que vous voyez, c'est que j'ai sudo -ssauté de bashma mkshcoquille, avec l'invite caractéristique que je lui ai définie. Et bien sûr, puisqu'il ne s'agit pas d'une action de connexion, car bashcela signifierait que le shell est généré en tant qu'instance de shell sans connexion. Dans mon cas, cependant, vous voyez qu'il $-n'y a pas de lettre l, qui serait là s'il s'agissait d'une instance de shell de connexion.

Enfin, la même idée s'applique à sudo suet sudo su -. Plus tard, on génère une instance de shell de connexion (c'est-à-dire que les fichiers spécifiques requis pour la connexion s'exécuteront) et l'ancien ne génère que des shells interactifs (c'est-à-dire que les fichiers de connexion ne s'exécutent pas).

bash-4.3$ sudo su
[sudo] password for xieerqi: 
root@eagle:/home/xieerqi# shopt login_shell
login_shell     off
root@eagle:/home/xieerqi# exit
bash-4.3$ sudo su -
[sudo] password for xieerqi: 
$ shopt login_shell
login_shell     on

Donc, techniquement, shopt login_shelln'a aucun rapport avec $SHELLquoi que ce soit. Pensez-y de cette façon: son but est de montrer comment bash fonctionne. $SHELLest censé refléter uniquement ce que vous avez attribué /etc/passwd.

Quant à la différence entre le shell de connexion et le shell sans connexion, elle a été expliquée par Gilles très respecté sur unix.stackexchange.com dans cette réponse .


Amusement supplémentaire

Voici quelque chose d'amusant que vous pouvez essayer. Comme vous le savez peut-être déjà, un shell de connexion s'exécutera .profile(et .bashrcpuisque Ubuntu .profile est configuré pour le faire ), mais l'enfer non-connecté exécutera uniquement un .bashrcfichier. Nous pouvons donc tester avec echolaquelle de ces commandes exécute un shell de connexion et laquelle ne le fait pas, et nous attendons deux lignes de echoshell de connexion et une seule pour les non-login.

$ echo "echo 'hi,i am .profile'"  >> .profile
$ echo "echo 'hi, i am .bashrc'" >> .bashrc
$ sudo -i
hi, i am .bashrc
hi,i am .profile
$ sudo su
hi, i am .bashrc
root@eagle:~# sudo su -
hi, i am .bashrc
hi,i am .profile
$ sudo -s
hi, i am .bashrc
root@eagle:~# 

Assez convenablement, ceux avec deux lignes de sortie se seront login_shellmis à on.

Sergiy Kolodyazhnyy
la source
Merci @Serg et @Zanna. Maintenant $SHELLet login_shell/non-login_shellclarifié. Mais d'où shoptviennent les détails? Est-ce de echo $0?
prado
1
@prado Je dirais que oui, puisque le premier caractère de $0est utilisé pour indiquer si un shell est un shell de connexion, donc if shoptvérifierait cette variable - bien sûr, c'est parfaitement acceptable. Cependant, il y a probablement plus que ce que l'on voit. shoptprobablement Pour cette question, je n'ai pas de réponse difficile, car je ne connais pas très bien le code source de bash.
Sergiy Kolodyazhnyy
@prado Bash peut être démarré en tant que shell de connexion soit en ayant le premier caractère de $ 0 be -, soit en utilisant l' -loption.
muru
@prado vous pouvez lire sur l'invocation et les options de bash dans la page de manuel. par exemple, la section de SHELL BUILTIN COMMAND dit login_shell The shell sets this option if it is started as a login shell (see INVOCATION above). The value may not be changed.que le shopt login_shellbash semble être à sens unique vous permet de découvrir - par programme comment savoir comment il a été démarré. l'autre solution serait[[ -o login ]]
the_velour_fog
11

Comme @Serg l'explique dans cette réponse sur la façon de savoir quel shell vous exécutez , la SHELLvariable est juste le shell par défaut de l'utilisateur actuel comme lu dans /etc/passwd:

$ grep zanna /etc/passwd
zanna:x:1000:1000:Zanna,,,:/home/zanna:/bin/bash

donc si je echo $SHELLreviendrai toujours /bin/bash:

$ zsh
% echo $SHELL
/bin/bash

Que ce soit ou non le shell est un shell de connexion, est un sh ell opt ion déterminé au moment où le shell est lancé. Le programme shell stocke ces informations avec tous ses autres paramètres et variables. La shoptcommande fournit un moyen de voir ces informations et, si possible pour l'option en question, de les définir ou de les désactiver (ce n'est pas le cas pour login_shelllequel, bien sûr, dépend du processus utilisé pour démarrer le shell)

Les sudooptions du programme déterminent comment ces différents types de shell racine seront démarrés:

entrez la description de l'image ici

Zanna
la source
1
Bonne explication. Je pense que vous avez expliqué quoi shoptet que vous login_shellêtes censé représenter bien mieux que cela dans ma réponse.
Sergiy Kolodyazhnyy
@Serg merci :) Je pense que votre explication est plus approfondie :)
Zanna
3

man bash:

Un shell de connexion est celui dont le premier caractère de l'argument zéro est un -, ou un a commencé avec l' --loginoption.

man login:

La valeur de $HOME, $SHELL[...] est définie en fonction des champs appropriés dans la saisie du mot de passe.

En bref:

  • Un shell est un shell de connexion s'il a été appelé en tant que shell de connexion.
  • La variable d'environnement $SHELLest définie par loginou par le programme appelant, par exemple su. Le shell lui-même ne le définit pas.
  • shopt montre les options du shell actuellement en vigueur.
AlexP
la source