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 ?
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. "
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".
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.
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"
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
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
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
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
-t
commutateurVous 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 .