web-dev-qa-db-fra.com

Différence entre le shell de connexion et le shell sans connexion?

Je comprends la différence fondamentale entre un shell interactif et un shell non interactif. Mais qu'est-ce qui différencie exactement un shell de connexion d'un shell sans connexion?

Pouvez-vous donner des exemples d'utilisation d'un shell interactif sans connexion ?

349
Igorio

Un shell de connexion est le premier processus qui s'exécute sous votre ID utilisateur lorsque vous vous connectez à une session interactive. Le processus de connexion indique au Shell de se comporter comme un Shell de connexion avec une convention: en passant l'argument 0, qui est normalement le nom de l'exécutable du Shell, avec un - caractère ajouté (par exemple -bash alors que ce serait normalement bash. Les shells de connexion lisent généralement un fichier qui fait des choses comme définir des variables d'environnement: /etc/profile et ~/.profile pour le Bourne Shell traditionnel, ~/.bash_profile en plus pour bash, /etc/zprofile et ~/.zprofile pour zsh, /etc/csh.login et ~/.login pour csh, etc.

Lorsque vous vous connectez sur une console texte, ou via SSH, ou avec su -, vous obtenez un login interactif Shell. Lorsque vous vous connectez en mode graphique (sur un gestionnaire d'affichage X ), vous n'obtenez pas de shell de connexion, mais un gestionnaire de session ou un gestionnaire de fenêtres.

Il est rare d'exécuter un shell de connexion non interactif , mais certains paramètres X le font lorsque vous vous connectez avec un gestionnaire d'affichage, afin d'organiser la lecture les fichiers de profil. Autres paramètres (cela dépend de la distribution et du gestionnaire d'affichage) lire /etc/profile et ~/.profile explicitement, ou ne les lisez pas. Une autre façon d'obtenir un shell de connexion non interactif consiste à se connecter à distance avec une commande passée par une entrée standard qui n'est pas un terminal, par ex. ssh example.com <my-script-which-is-stored-locally (par opposition à ssh example.com my-script-which-is-on-the-remote-machine, qui exécute un shell non interactif et sans connexion).

Lorsque vous démarrez un Shell dans un terminal dans une session existante (écran, terminal X, tampon de terminal Emacs, un Shell à l'intérieur d'un autre, etc.), vous obtenez un interactif, sans connexion Shell. Ce Shell peut lire un fichier de configuration Shell (~/.bashrc pour bash invoqué comme bash, /etc/zshrc et ~/.zshrc pour zsh, /etc/csh.cshrc et ~/.cshrc pour csh, le fichier indiqué par la variable ENV pour les shells compatibles POSIX/XSI tels que dash, ksh et bash lorsqu'elle est invoquée en tant que sh, $ENV si défini et ~/.mkshrc pour mksh, etc.).

Lorsqu'un shell exécute un script ou une commande passée sur sa ligne de commande, il s'agit d'un shell non interactif, sans connexion . De tels shells s'exécutent tout le temps: il est très fréquent que lorsqu'un programme appelle un autre programme, il exécute vraiment un petit script dans un Shell pour appeler cet autre programme. Certains shells lisent un fichier de démarrage dans ce cas (bash exécute le fichier indiqué par le BASH_ENV variable, zsh s'exécute /etc/zshenv et ~/.zshenv), mais c'est risqué: le Shell peut être invoqué dans toutes sortes de contextes, et il n'y a pratiquement rien que vous puissiez faire qui ne puisse casser quelque chose.

 Je simplifie un peu, voir le manuel pour les détails sanglants.

Pour savoir si vous êtes dans un shell de connexion:

Prompt> echo $0
-bash # "-" is the first character. Therefore, this is a login Shell.

Prompt> echo $0
bash # "-" is NOT the first character. This is NOT a login Shell.

Dans Bash, vous pouvez également utiliser shopt login_Shell :

Prompt> shopt login_Shell
login_Shell     off

(ou on dans un shell de connexion).

Des informations peuvent être trouvées dans man bash (recherche d'invocation). En voici un extrait:

Un shell de connexion est un shell dont le premier caractère de l'argument zéro est un - ou un commençant par l'option --login.

Vous pouvez le tester vous-même. Chaque fois que vous SSH, vous utilisez un shell de connexion. Par exemple:

Prompt> ssh user@localhost
user@localhost's password:
Prompt> echo $0
-bash

L'importance d'utiliser un shell de connexion est que tous les paramètres de /home/user/.bash_profile sera exécuté. Voici un peu plus d'informations si vous êtes intéressé (de man bash)

"Lorsque bash est appelé en tant que shell de connexion interactif, ou en tant que shell non interactif avec l'option --login, il lit et exécute d'abord les commandes du fichier/etc/profile, si ce fichier existe. Après avoir lu ce fichier, il cherche des ~/.bash_profile, ~/.bash_login, et ~/.profile, dans cet ordre, et lit et exécute les commandes de la première qui existe et qui est lisible. L'option --noprofile peut être utilisée au démarrage du shell pour empêcher ce comportement. "

53
Timothy Pulliam

Dans un shell de connexion, argv[0][0] == '-'. C'est ainsi qu'il sait qu'il s'agit d'un shell de connexion.

Et puis, dans certaines situations, il se comporte différemment en fonction de son état "shell de connexion". Par exemple. un shell, qui n'est pas un shell de connexion, n'exécuterait pas de commande de "déconnexion".

23
BOPOHOK

Un Shell démarré dans un nouveau terminal dans une interface graphique serait un Shell interactif sans connexion. Il source votre .bashrc, mais pas votre .profile, par exemple.

18
Julian

Je vais développer la grande réponse de Gilles, combinée avec la méthode de Timothy pour vérifier le type de shell de connexion.

Si vous aimez voir les choses par vous-même, essayez les extraits et les scénarios ci-dessous.

Vérifier si Shell est (non) interactif

if tty -s; then echo 'This is interactive Shell.'; else echo 'This is non-interactive Shell.'; fi

Vérification de la connexion (non) de Shell

Si la sortie de echo $0 commence avec -, c'est le shell de connexion (echo $0 exemple de sortie: -bash). Sinon, c'est un shell sans connexion (echo $0 exemple de sortie: bash).

if echo $0 | grep -e ^\- 2>&1>/dev/null; then echo "This is login Shell."; else echo "This is non-login Shell."; fi;

Combinons les deux ci-dessus pour obtenir les deux informations à la fois:

THIS_Shell_INTERACTIVE_TYPE='non-interactive'; 
THIS_Shell_LOGIN_TYPE='non-login'; 
if tty -s; then THIS_Shell_INTERACTIVE_TYPE='interactive'; fi; 
if echo $0 | grep -e ^\- 2>&1>/dev/null; then THIS_Shell_LOGIN_TYPE='login'; fi;
echo "$THIS_Shell_INTERACTIVE_TYPE/$THIS_Shell_LOGIN_TYPE"

Scénarios:

Session SSH typique sans options spéciales

ssh [email protected]
Welcome to Ubuntu 16.04.5 LTS (GNU/Linux 4.4.0-1083-aws x86_64)

ubuntu@ip-172-31-0-70:~$ THIS_Shell_INTERACTIVE_TYPE='non-interactive';
ubuntu@ip-172-31-0-70:~$ THIS_Shell_LOGIN_TYPE='non-login';
ubuntu@ip-172-31-0-70:~$ if tty -s; then THIS_Shell_INTERACTIVE_TYPE='interactive'; fi;
ubuntu@ip-172-31-0-70:~$ if echo $0 | grep -e ^\- 2>&1>/dev/null; then THIS_Shell_LOGIN_TYPE='login'; fi;
ubuntu@ip-172-31-0-70:~$ echo "$THIS_Shell_INTERACTIVE_TYPE/$THIS_Shell_LOGIN_TYPE"

interactive/login

Exécution de script ou exécution explicite via un nouveau shell

ubuntu@ip-172-31-0-70:~$  bash -c 'THIS_Shell_INTERACTIVE_TYPE='non-interactive'; THIS_Shell_LOGIN_TYPE='non-login'; if tty -s; then THIS_Shell_INTERACTIVE_TYPE='interactive'; fi; if echo $0 | grep -e ^\- 2>&1>/dev/null; then THIS_Shell_LOGIN_TYPE='login'; fi; 
echo "$THIS_Shell_INTERACTIVE_TYPE/$THIS_Shell_LOGIN_TYPE"'

interactive/non-login

Exécuter un script local à distance

ssh [email protected] < checkmy.sh
Pseudo-terminal will not be allocated because stdin is not a terminal.
Welcome to Ubuntu 16.04.5 LTS (GNU/Linux 4.4.0-1083-aws x86_64)

non-interactive/login

Exécution d'une commande sur ssh à distance

ssh [email protected] 'THIS_Shell_INTERACTIVE_TYPE='non-interactive'; THIS_Shell_LOGIN_TYPE='non-login'; if tty -s; then THIS_Shell_INTERACTIVE_TYPE='interactive'; fi; if echo $0 | grep -e ^\- 2>&1>/dev/null; then THIS_Shell_LOGIN_TYPE='login'; fi; echo "$THIS_Shell_INTERACTIVE_TYPE/$THIS_Shell_LOGIN_TYPE"'

non-interactive/non-login

Exécution d'une commande sur ssh à distance avec -t commutateur

Vous pouvez explicitement demander un shell interactif lorsque vous souhaitez exécuter la commande à distance via ssh en utilisant -t commutateur.

ssh [email protected] -t 'THIS_Shell_INTERACTIVE_TYPE='non-interactive'; THIS_Shell_LOGIN_TYPE='non-login'; if tty -s; then THIS_Shell_INTERACTIVE_TYPE='interactive'; fi; if echo $0 | grep -e ^\- 2>&1>/dev/null; then THIS_Shell_LOGIN_TYPE='login'; fi; echo "$THIS_Shell_INTERACTIVE_TYPE/$THIS_Shell_LOGIN_TYPE"'

interactive/non-login

Remarque: sur le sujet expliquant pourquoi l'exécution de la commande à distance n'est pas login Shell plus d'infos ici .

5
Patrik Stas