J'ai remarqué que lorsque j'exécute une commande directement sur un hôte SSH en utilisant la ssh <host> <command>
syntaxe, je vois la sortie de .bashrc
mais pas la sortie de .bash_profile
(ou .profile
).
Par exemple, si je place la commande suivante en haut des deux fichiers,
echo ${BASH_SOURCE[0]}
et source manuellement .bash_profile
(quelles sources .bashrc
à leur tour), je vais voir
$ . .bash_profile
.bash_profile
.bashrc
C'est la même sortie que je vois si je me connecte à cet ordinateur à distance via SSH, en utilisant le ssh <host>
formulaire de la commande. (Et si je range .bash_profile
temporairement ailleurs, aucune de ces lignes ne se répercute.)
Cependant, si j'exécute une commande directement sur la machine distante sous la ssh <host> <command>
forme de ssh
, la sortie ressemble à ceci:
$ ssh <host> echo foo
/home/rlue/.bashrc
foo
Ma compréhension est que la différence entre .bash_profile
et .bashrc
est que le premier est pour les shells de connexion tandis que le second est pour les shells interactifs sans connexion .
J'ai conclu ce qui suit:
ssh <host>
sources uniquement.bash_profile
,ssh <host> <command>
sources uniquement.bashrc
, ce qui signifie- le premier est un shell de connexion et le second ne l'est pas.
Ces conclusions sont-elles correctes? Pourquoi est-il ssh <host> <command>
traité comme un shell interactif sans connexion? SSH ne se connecte-t-il toujours pas à la machine distante pour exécuter la commande?
.bashrc
? Ce fichier n'est pas censé produire de sortie. Toute sortie de.bashrc
peut casser tous les outils en utilisant ssh comme transport..bashrc
lançaient une erreur, tandis que des lignes similaires.bash_profile
ne l'étaient pas. J'en ai profité pour enquêter sur l'écart avant de corriger les lignes incriminées.Réponses:
OpenSSH (probablement ce que vous exécutez) décide de créer ou non un shell de connexion, et il ne le fait que si vous n'exécutez pas une commande spécifique. De
man ssh
:C'est donc un choix d'implémentation pour le serveur ssh, qu'il veuille ou non créer un shell de connexion, et si vous donnez une commande à exécuter, ce n'est pas le cas.
Bien
ssh
qu'il effectue une connexion, si vous lui faites exécuter une commande et quittez, cela ressemble beaucoup plus à la création d'un shell juste pour exécuter cette commande qu'à l'obtention d'un environnement de connexion. Il semble, étant donné que, que les gens qui écrivent OpenSSH ont décidé de le traiter comme ce genre de tâche.Ils créent un shell non interactif et sans connexion pour exécuter la commande, car c'est l'esprit d'exécuter une commande dans un autre contexte / shell. Normalement, cependant, les shells non interactifs ne seraient pas automatiquement source,
~/.bashrc
ce qui se produit clairement ici.bash
essaie en fait de nous aider ici. À partir des documentsla source
ssh
nécessite une connexion, les exécutants ont apparemment décidé que , dans certaines circonstances, par exemple, en lui demandant d'exécuter une commande et retour, font pas besoin / bénéficier des étapes supplémentaires qu'un shell de connexion prend, et donc ils sautent cela. Donc, en effet, il y a un shell qui est exécuté, je suppose principalement pour configurer l'environnement, et puisque le shell ne sera pas fourni à l'utilisateur qui s'est connecté, ils le traitent comme si l'utilisateur venait de démarrer un nouveau shell pour exécuter ce commandessh <host> <command>
n'hérite de l'environnement d'aucun shell de connexion existant. Par exemple,$ ssh <host> \$PATH
renvoie le chemin tel qu'il serait sans sourcing.bash_profile
(ou.profile
, pour ainsi dire) ... Dans un sens pratique, pourquoi voudriez-vous contourner cette étape?PATH
en.profile
- est -ce pas exactement le genre de chose que vous voudriez chargé avant d' exécuter une commande arbitraire sur un hôte distant?Le pourquoi de ce comportement se situe à un niveau inférieur à celui des shells:
ssh host
(le cas "login shell") utilise un pseudoterminal sur l'hôte distant, pour communiquer entre lesshd
processus serveur et le shell;ssh host command
utilise des tuyaux entresshd
etcommand
, à la place. Les pseudoterminaux sont nécessaires pour faire un usage interactif d'un interpréteur de commandes, comme un shell, ou le mode " read-eval-print " d'un langage de script; ils implémentent un tas de fonctionnalités conviviales comme la possibilité de revenir en arrière sur les fautes de frappe. Mais ils ont plus de surcharge et (selon la configuration) ne permettent pas à des données arbitraires de passer sans modification, donc SSH évite de les utiliser lorsque l'interaction ne se produira pas.Parfois, l'heuristique de commande / pas de commande de SSH se trompe; il peut être remplacé par les commutateurs
-t
et-T
. Par exemple, pour vous connecter à une machine distante et rattacher immédiatement unescreen
session suspendue , vous devez le fairessh -t host screen -R
;ssh host screen -R
entraînerascreen
à se plaindre de ne pas être connecté à un terminal. Je ne peux pas penser à une situation où vous vraiment envie d'utiliser-T
, mais il est là si jamais vous ne trouvez un.la source
Vous devez d'abord voir les différents types, vous pouvez lire ceci:
/unix/170493/login-non-login-and-interactive-non-interactive-shells
Maintenant, si vous ouvrez votre bashrc, vous verrez au début ceci:
Cela signifie que selon la façon dont vous accédez au système, ce fichier charge le code à l'intérieur ou non.
la source
.bashrc
peut être écrit de manière à ne pas provenir s'il est appelé dans un contexte non interactif ( c'est-à-dire s'il n'y a pas de «déclaration rapide» /$PS1
variable). Maisssh <host> <command>
est décidément non interactif ; c'est-à-dire qu'il ne déclenche pas d' invite de commandes. Alors, pourquoi OpenSSH serait-il conçu pour créer une invite interactive sans connexion (une qui essaie de se procurer.bashrc
) pour ce cas d'utilisation apparemment sans connexion et non interactif ??