`ssh <host>` es un shell de inicio de sesión, pero `ssh <host> <command>` no lo es?


12

Me di cuenta de que cuando ejecuto un comando directamente en un host SSH usando la ssh <host> <command>sintaxis, veo la salida de ( .bashrcpero) la salida de .bash_profile(o .profile).

Por ejemplo, si coloco el siguiente comando en la parte superior de ambos archivos,

echo ${BASH_SOURCE[0]}

y fuente manualmente .bash_profile(que fuentes .bashrca su vez), veré

$ . .bash_profile
.bash_profile
.bashrc

Esta es la misma salida que veo si inicio sesión en esta computadora de forma remota a través de SSH, utilizando la ssh <host>forma del comando. (Y si guardo .bash_profileen otro lugar temporalmente, ninguna de estas líneas tiene eco).

Sin embargo, si ejecuto un comando directamente en la máquina remota con la ssh <host> <command>forma de ssh, entonces la salida se ve así:

$ ssh <host> echo foo
/home/rlue/.bashrc
foo

Tengo entendido que la diferencia entre .bash_profiley .bashrces que el primero es para shells de inicio de sesión, mientras que el segundo es para shells interactivos, sin inicio de sesión .

He concluido lo siguiente:

  1. ssh <host>solo fuentes .bash_profile, mientras
  2. ssh <host> <command>solo fuentes .bashrc, lo que significa
  3. el primero es un shell de inicio de sesión y el segundo no.

¿Son correctas estas conclusiones? ¿Por qué se ssh <host> <command>trata como un shell interactivo sin inicio de sesión? ¿SSH todavía no está iniciando sesión en la máquina remota para ejecutar el comando?


salida de .bashrc? Se supone que ese archivo no produce ningún resultado. Cualquier salida de .bashrcpuede romper todas las herramientas usando ssh como su transporte.
kasperd

Lo suficientemente justo. En este caso, un par de líneas .bashrcestaban arrojando un error, mientras que líneas similares .bash_profileno. Aproveché la oportunidad para investigar la discrepancia antes de corregir las líneas ofensivas.
Ryan Lue

Respuestas:


12

OpenSSH (muy probablemente lo que está ejecutando) decide si crear o no un shell de inicio de sesión, y solo lo hace si no está ejecutando un comando específico. De man ssh:

 If command is specified, it is executed on the remote host instead of a
 login shell.

Por lo tanto, es una opción de implementación para el servidor ssh si desea crear un shell de inicio de sesión o no, y si le da un comando para ejecutar, no lo hace.

Si bien sshrealiza un inicio de sesión, si tiene que ejecutar un comando y salir, en realidad es mucho más similar a crear un shell solo para ejecutar ese comando que para obtener un entorno de inicio de sesión. Parece, dado eso, que las personas que escriben OpenSSH decidieron tratarlo como ese tipo de tarea.

Crean un shell no interactivo y sin inicio de sesión para ejecutar el comando, porque ese es el espíritu de ejecutar un comando en otro contexto / shell. Sin embargo, normalmente, los shells no interactivos no se generarían automáticamente, lo ~/.bashrcque claramente está sucediendo aquí. bashen realidad está tratando de ayudarnos aquí. De los documentos

Invocado por un demonio de shell remoto

Bash intenta determinar cuándo se ejecuta con su entrada estándar conectada a una conexión de red, como cuando lo ejecuta el demonio de shell remoto, generalmente rshd, o el demonio de shell seguro sshd. Si Bash determina que se está ejecutando de esta manera, lee y ejecuta comandos desde ~ / .bashrc, si ese archivo existe y es legible. No hará esto si se invoca como sh. La opción --norc puede usarse para inhibir este comportamiento, y la opción --rcfile puede usarse para forzar la lectura de otro archivo, pero ni rshd ni sshd generalmente invocan el shell con esas opciones o permiten que se especifiquen.


"... se ejecuta en el host remoto en lugar de un shell de inicio de sesión". No entiendo esta dicotomía. ¿Se ejecuta el comando en el host remoto en lugar de en un shell de inicio de sesión , o se ejecuta el comando en el host remoto, en lugar de ejecutar un shell de inicio de sesión allí? Si es lo primero, ¿cómo es esto o lo otro? (¿no son normalmente ambos? ) Si este último, todavía se ejecuta en el contexto de algún shell, ¿no? (¿una interactiva, sin inicio de sesión?) Entonces, mi pregunta también es sobre la semántica: ¿qué significa "shell de inicio de sesión" y por qué OpenSSH estaría diseñado para no crear uno para comandos individuales?
Ryan Lue

@RyanLue Los diferentes "sabores" de los shells hacen que ciertas tareas sean más fáciles / más seguras / optimizadas, etc. Si bien hacer un sshsí requiere un inicio de sesión, los implementadores aparentemente decidieron que, en algunas circunstancias, p. Ej. no necesita / se beneficia de los pasos adicionales que toma un shell de inicio de sesión, por lo que se saltan eso. De hecho, hay un shell que se ejecuta, supongo principalmente que configura el entorno, y dado que el shell no se proporcionará al usuario que inició sesión, lo tratan como si el usuario acabara de iniciar un nuevo shell para ejecutarlo. comando
Eric Renouf

"Entonces, de hecho, hay un shell que se ejecuta, supongo que principalmente configuro el entorno ..." <pero acabo de experimentar con esto, y parece que ssh <host> <command>no hereda el entorno de ningún shell de inicio de sesión existente. Por ejemplo, $ ssh <host> \$PATHdevuelve el camino como sería sin abastecimiento .bash_profile(o .profile, por así decirlo) ... En un sentido práctico, ¿por qué querría eludir ese paso?
Ryan Lue

"... los implementadores aparentemente decidieron que, en algunas circunstancias, por ejemplo, pedirle que ejecute un comando y regresar, no necesitan / se benefician de los pasos adicionales que toma un shell de inicio de sesión, por lo que se saltan eso". <también, específicamente buscando aclaraciones / ideas sobre esta elección de diseño. Defino mi PATHen .profile- no es que exactamente el tipo de cosas que te gustaría cargado antes de ejecutar un comando arbitrario en un host remoto?
Ryan Lue

1
@RyanLue, el servidor Boks ssh distingue los distintos usos de ssh y puede otorgar permisos para cada uno. Inicio de sesión remoto, ejecución remota, copia remota, tal vez esto ayude a comprender por qué tendría el comportamiento que describe. El inicio de sesión remoto (uso interactivo) puede ser demasiado pedir en un entorno de alta seguridad. Openssh puede restringirse mediante el uso de rbash / rksh y 'logout' en .bash_profile o chroot.
bbaassssiiee

4

El motivo de este comportamiento se encuentra en un nivel más bajo que los shells: ssh host(el caso de "shell de inicio de sesión") utiliza un pseudoterminal en el host remoto, para comunicarse entre el sshdproceso del servidor y el shell; ssh host commandusa tuberías entre sshdy command, en su lugar. Los pseudoterminales son necesarios para hacer un uso interactivo de un intérprete de comandos, como un shell, o el modo " leer-evaluar-imprimir " de un lenguaje de secuencias de comandos; implementan un montón de características amigables para los humanos, como la posibilidad de retroceder sobre errores tipográficos. Pero tienen más gastos generales y (dependiendo de la configuración) no permiten que los datos arbitrarios pasen sin modificaciones, por lo que SSH evita usarlos cuando la interacción no va a suceder.

A veces, la orden heurística de comando / no comando de SSH se equivoca; se puede anular con los interruptores -ty -T. Por ejemplo, para iniciar sesión en una máquina remota e inmediatamente volver a conectar una screensesión suspendida , debe hacerlo ssh -t host screen -R; ssh host screen -Rhará screenquejarse de no estar conectado a un terminal. No puedo pensar en una situación en la que realmente quieras usar -T, pero está ahí si alguna vez encuentras una.


1

Primero necesitas ver los diferentes tipos, puedes leer esto:

/unix/170493/login-non-login-and-interactive-non-interactive-shells

Ahora, si abre su bashrc, verá al principio esto:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

Eso significa que dependiendo de cómo esté accediendo al sistema, este archivo carga el código dentro o no.


De acuerdo, pero esto plantea una pregunta interesante: .bashrcpuede escribirse para que no se obtenga si se llama en un contexto no interactivo ( es decir, si no hay una "declaración rápida" / $PS1variable). Pero ssh <host> <command> es decididamente no interactivo ; es decir, no genera un símbolo del sistema. Entonces, ¿por qué OpenSSH estaría diseñado para crear una solicitud interactiva que no sea de inicio de sesión (una que intente obtener .bashrc) para este caso de uso aparentemente no interactivo?
Ryan Lue
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.