Al hacer ssh'ing, ¿cómo puedo configurar una variable de entorno en el servidor que cambie de sesión a sesión?

92

Cuando entro sshen un servidor, ¿cómo puedo pasar una variable de entorno del cliente al servidor? Esta variable de entorno cambia entre diferentes invocaciones de ssh, por lo que no quiero sobrescribir $HOME/.ssh2/environmentcada vez que hago una llamada ssh. ¿Cómo puedo hacer esto?

Ross Rogers
fuente
2
Tu pregunta debe ser un poco más específica.
Ignacio Vazquez-Abrams
3
La pregunta fue lo suficientemente clara para mí. Sin embargo, desde la sshpágina de manual, no veo otra forma de hacerlo que no sea configurar la variable manualmente una vez que haya iniciado sesión en el servidor, a menos que modifique ~ / .ssh2 / environment.
garyjohn
¿Es una variable diferente cada vez? O un valor diferente?
Dennis Williamson
1
Al revés, ya que esto ya es más popular. No importa que sea más viejo.
kenorb

Respuestas:

110

Por supuesto, puede establecer la variable de entorno dentro del comando, sin embargo, tendrá que tener cuidado al citar: recuerde que su shell analizará su línea de comando local, y luego el shell remoto tendrá que ir a la cadena. recibe.

Si desea que una variable obtenga el mismo valor en el servidor que tiene en el cliente, pruebe la SendEnvopción:

ssh -o SendEnv = MYVAR server.example.com mycommand

Sin embargo, esto requiere soporte del servidor. Con OpenSSH, se debe autorizar el nombre de la variable /etc/sshd_config.

Si el servidor solo permite ciertos nombres de variables específicas, puede evitarlo; por ejemplo, una configuración común permite LC_*, y puede hacer lo siguiente:

ssh -o SendEnv = LC_MYVAR server.example.com 'MYVAR = $ LC_MYVAR; desarmado LC_MYVAR; exportar MYVAR; mycommand '

Si incluso LC_*no es una opción, puede pasar información en la TERMvariable de entorno, que siempre se copia (sin embargo, puede haber un límite de longitud). Todavía tendrá que asegurarse de que el shell remoto no restrinja la TERMvariable para designar un tipo de terminal conocido. Pase la -topción a ssh si no está iniciando un shell interactivo remoto.

env TERM = "información adicional: $ TERM" ssh -t server.example.com 'MYVAR = $ {TERM%: *}; PLAZO = $ {PLAZO ## *:}; exportar MYVAR; mycommand '

Otra posibilidad es definir la variable directamente en el comando:

ssh -t server.example.com 'export MYVAR = "información adicional"; mycommand '

Por lo tanto, si pasa una variable local:

ssh -t server.example.com 'export MYVAR =' "'$ LOCALVAR'" '; mycommand '

Sin embargo, tenga cuidado con los problemas de citas: el valor de la variable se interpolará directamente en el fragmento de shell ejecutado en el lado remoto. El último ejemplo anterior supone que $LOCALVARno contiene comillas simples ( ').

Gilles
fuente
2
Muchas gracias, estaba furioso porque las estúpidas variables LC_ * se exportan en ssh y su respuesta me indicó dónde buscar. Solo tengo que deshabilitar eso en ~ / .ssh / config
akostadinov
1
Estoy en la situación del póster original, pero la variable que quería reenviar es TERM, así que estoy un poco desconcertado por su respuesta. ¿Se ha deshabilitado este reenvío automático de TERM por versiones recientes de OpenSSH?
Doub
1
@Doub El valor por defecto es para rechazar todas las variables de entorno en el lado del servidor, con AcceptEnvlas directivas en sshd_configtan deseada por el administrador. Pero TERMse trata especialmente, por lo que sé, no hay forma de filtrarlo en el lado del servidor (se establece en el entorno del shell, independientemente de cualquier configuración). ¿Estás seguro de que no hay un script de perfil que lo anule (como /etc/profileo ~/.profileo ~/.bashrc)?
Gilles
2
@Gilles: Lo probé nuevamente, y a menos que agregue explícitamente TERM a mi directiva AcceptEnv, el TERM no se transfiere. No abro un shell, sino que ejecuto un comando directamente, por ejemplo: "ssh -o SendEnv = TERM shell.example.com env". Eso imprime todas las variables de entorno, y TERM solo aparece si está en SendEnv en el cliente y AcceptEnv en el servidor. Si ejecuto "ssh -o SendEnv = TERM shell.example.com echo \ $ {TERM}" sin el AcceptEnv o SendEnv, imprime "tonto", que no estoy seguro de dónde viene (env ni siquiera lista TERM en ese caso).
Doub
77
@Doub Oh, ya veo. TERMsolo se transmite si el cliente solicita al servidor que asigne un tty. Si no hay terminal en el lado remoto, sería inútil transmitir TERM. Cuando especifica un comando, si desea tener un terminal en el lado remoto, necesita la -topción de línea de comando (o RequestTTYen ~/.ssh/config).
Gilles
12

Si puede administrar el host de destino, puede configurar sshd para permitir pasar sus variables de entorno locales al host de destino.

Desde la página de manual de sshd_config:

 PermitUserEnvironment
     Specifies whether ~/.ssh/environment and environment= options in
     ~/.ssh/authorized_keys are processed by sshd.  The default is
     "no".  Enabling environment processing may enable users to bypass
     access restrictions in some configurations using mechanisms such
     as LD_PRELOAD.

la configuración de sshd generalmente vive en /etc/ssh/sshd_config

Duncan Beevers
fuente
77
¡Es muy útil saber que esto está configurado en "no" de forma predeterminada!
jathanism
6

Entonces, en su cliente, ¿tiene alguna variable de entorno y desea que esté disponible para el comando remoto? No creo que haya una manera de que ssh lo pase mágicamente, pero probablemente puedas hacer algo como esto. En lugar de usar, diga:

ssh remote.host my_command

Puedes hacerlo:

ssh remote.host env ENV_VAR=$ENV_VAR my_command
pioto
fuente
"probablemente"? Desearía leer eso antes de intentar esta respuesta. No funciono para mi.
tishma
1
¿Le gustaría elaborar cualquier error recibido, etc.?
pioto
1
@pioto Podría estar citando, por ejemplo, si ENV_VAR tiene espacios en él
Martin C. Martin
En Mac, debe tener la opción -t para una versión interactiva, de lo contrario, parece atascado. Entonces esto podría funcionar: $ ssh -t remote.host env ENV_VAR = $ ENV_VAR my_command
muenalan
3

La respuesta de @ emptyset (que no funcionó para mí) me llevó a esta respuesta:

Puede agregar este comando a su ~/.ssh/authorized_keysarchivo:

command="/usr/bin/env VARIABLE=<something> $SHELL" ssh-rsa <key>

export VARIABLE=<something>salía inmediatamente y la conexión SSH se cerró (me bloqueó el acceso al servidor), mientras /usr/bin/env ... $SHELLque ejecutará su shell predeterminado con un entorno modificado.

madprog
fuente
Esto simplemente se cuelga al iniciar sesión para mí. Cuando lo elimino, SSH vuelve a la normalidad y obtengo mi shell de inicio de sesión habitual.
Nick Sweeting
@NickSweeting, ¿has intentado reemplazarlo $SHELLpor un caparazón real? Compruebe también que / usr / bin / env existe en el servidor. Sin embargo, la solución no es perfecta: he notado que se cuelga cuando quería usar scpo un comando en línea.
madprog
Sí, eso fue lo primero que intenté. Desafortunadamente, nunca funcionó, terminé habilitando PermitUserEnvironment yesy usando en environment="..."lugar de command="...".
Nick Sweeting
Esto está funcionando muy bien para mí.
Sr. Tao
3

En su cliente local, en su ~/.ssh/configpuede agregar SetEnv, por ejemplo

Host myhost
  SetEnv FOO=bar

Nota: Verificar man ssh_config.

Luego, en el servidor, asegúrese de permitir que el cliente pase ciertas variables de entorno en su /etc/ssh/sshd_configarchivo de configuración:

AcceptEnv LANG LC_* FOO BAR*

Nota: Verificar man sshd_config.

kenorb
fuente
1

Puede intentar invocar un comando personalizado, suponiendo que tenga una configuración de inicio de sesión ssh sin contraseña. En el servidor, edite su entrada ~ / .ssh / Authorized_keys que corresponda a la clave de su cliente:

command="export VARIABLE=<something>" ssh-rsa <key>

Mire este enlace en la sección Comando forzado para obtener un poco más de detalle.

conjunto vacio
fuente
1
Intenté esto, pero no funciona. Ejecuta el comando y sale, por lo que no hay sesión interactiva. ¿Es ese el comportamiento normal? Si es así, eso podría ser útil si todo lo que quiere hacer es permitir que una tecla específica active un comando específico, pero si desea pasar información que se usa en una sesión (como dice la pregunta), entonces es inútil para ese propósito . No hay sesión.
iconoclasta
1

Estaba haciendo una compilación personalizada de OpenSSH para un dispositivo con un cramfs en el directorio de inicio y / etc (Cram FS es de solo lectura) para que ~ / .ssh / environment no funcionaría sin reconstruir todo el FS y estos se desplegaron en campo dispositivos (sistemas integrados, de ahí el uso de CRAMFS). Puede especificar en sshd_config la ubicación del archivo authroized_keys, pero por alguna razón el entorno = solo funciona para las variables de entorno en ~ / .ssh / authroized_keys. Editar el / etc / profile no era una opción y tuve que cargar ssh en un directorio no estándar. En session.c después de child_set_env (... "MAIL" ...) simplemente agregue las variables de entorno que necesita (este es un truco que sé ...) pero solo en caso de que alguien necesite algunos envs codificados para una sesión si está compilando desde la fuente puedes hacer esto. TGI-FLOSS

Será
fuente
0

solo un comando simple:

ssh -t your_host_or_ip 'export some_var_name=whatever_you_want; bash'
grepit
fuente