Lorsque ssh'ing, comment définir une variable d'environnement sur le serveur qui change de session en session?

92

Lorsque je me sshconnecte à un serveur, comment puis-je transmettre une variable d'environnement du client au serveur? Cette variable d'environnement change entre les différents appels de ssh, je ne veux donc pas écraser $HOME/.ssh2/environmentchaque fois que je fais un appel ssh. Comment puis-je faire ceci?

Ross Rogers
la source
2
Votre question doit être un peu plus précise.
Ignacio Vazquez-Abrams le
3
La question était assez claire pour moi. Cependant, à partir de la sshpage de manuel, je ne vois pas d'autre moyen de le faire que de définir manuellement la variable une fois que vous êtes connecté au serveur, à moins que vous ne modifiiez ~ / .ssh2 / environment.
garyjohn
Est-ce une variable différente à chaque fois? Ou une valeur différente?
Dennis Williamson
1
Autrement, c'est déjà plus populaire. Peu importe qu'il soit plus vieux.
Kenorb

Réponses:

110

Bien sûr, vous pouvez définir la variable d'environnement à l'intérieur de la commande, mais vous devrez faire attention à la citation: rappelez-vous que votre shell va analyser votre ligne de commande locale et que le shell distant essaiera la chaîne qu'il contient. reçoit.

Si vous voulez qu'une variable obtienne la même valeur sur le serveur que sur le client, essayez l' SendEnvoption:

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

Cela nécessite cependant le support du serveur. Avec OpenSSH, le nom de la variable doit être autorisé dans /etc/sshd_config.

Si le serveur n'autorise que certains noms de variables spécifiques, vous pouvez contourner ce problème. Par exemple, une configuration commune permet LC_*, et vous pouvez faire ce qui suit:

ssh -o SendEnv = LC_MYVAR serveur.exemple.com 'MYVAR = $ LC_MYVAR; non défini LC_MYVAR; exporter MYVAR; ma commande '

Si pair LC_*n'est pas une option, vous pouvez transmettre des informations dans la TERMvariable d'environnement, qui est toujours copiée (il peut toutefois exister une limite de longueur). Vous devrez toujours vous assurer que le shell distant ne restreint pas la TERMvariable pour désigner un type de terminal connu. Passez l' -toption à ssh si vous ne démarrez pas un shell interactif distant.

env TERM = "informations supplémentaires: $ TERM" ssh -t server.example.com 'MYVAR = $ {TERM%: *}; TERM = $ {TERM ## *:}; exporter MYVAR; ma commande '

Une autre possibilité consiste à définir la variable directement dans la commande:

ssh -t server.example.com 'export MYVAR = "informations supplémentaires"; ma commande '

Ainsi, en passant une variable locale:

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

Cependant, méfiez-vous des problèmes de citation: la valeur de la variable sera interpolée directement dans l'extrait de shell exécuté du côté distant. Le dernier exemple ci-dessus suppose que $LOCALVARne contient pas de guillemets simples ( ').

Gilles
la source
2
Merci beaucoup, j'étais furieux que les stupides variables LC_ * soient exportées sur ssh et votre réponse m'a indiqué où chercher. Je dois juste désactiver cela dans ~ / .ssh / config
akostadinov
1
Je suis dans la situation de l’affiche originale, mais la variable que je voulais transmettre est TERM, alors je suis un peu perplexe devant votre réponse. Ce transfert automatique de TERM a-t-il été désactivé par les versions récentes d'OpenSSH?
Doub
1
@Doub La valeur par défaut consiste à refuser toutes les variables d'environnement côté serveur, avec les AcceptEnvdirectives entrées sshd_configcomme souhaité par l'administrateur. Mais TERMest traité spécialement, pour autant que je sache, il n’existe aucun moyen de le filtrer côté serveur (il est défini dans l’environnement du shell indépendamment de tout paramètre de configuration). Êtes-vous sûr qu'il n'y a pas de script de profil qui le remplace (comme /etc/profileou ~/.profileou ~/.bashrc)?
Gilles
2
@Gilles: Je l'ai testé à nouveau et, à moins d'ajouter explicitement TERM à ma directive AcceptEnv, le terme TERM n'est pas transmis. Je n’ouvre pas de shell, mais exécute directement une commande, par exemple: "ssh -o SendEnv = TERM shell.example.com env". Cela imprime toutes les variables d’environnement, et TERM n’apparaît que s’il est en SendEnv sur le client et AcceptEnv sur le serveur. Si je lance "ssh -o SendEnv = TERM shell.exemple.com echo \ $ {TERM}" avec AcceptEnv ou SendEnv, il affiche "bête", dont je ne suis pas sûr d’où il provient (env même liste TERM dans ce cas).
Doub
7
@ Doub Oh, je vois. TERMn'est transmis que si le client demande au serveur d'allouer un tty. S'il n'y a pas de terminal du côté distant, il serait inutile de transmettre TERM. Lorsque vous spécifiez une commande, si vous souhaitez avoir un terminal du côté distant, vous avez besoin de l' -toption de ligne de commande (ou RequestTTYin ~/.ssh/config).
Gilles
12

Si vous pouvez administrer l'hôte cible, vous pouvez configurer sshd pour permettre la transmission de vos variables d'environnement locales à l'hôte cible.

A partir de la page de manuel 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 configuration de sshd vit généralement à /etc/ssh/sshd_config

Duncan Beevers
la source
7
Il est très utile de savoir que ceci est réglé sur "non" par défaut!
Jathanism
6

Donc, sur votre client, vous avez une variable d’environnement et vous voulez que celle-ci soit disponible pour la commande à distance? Je ne pense pas qu'il y ait un moyen de faire passer ssh magiquement, mais vous pouvez probablement faire quelque chose comme ça. Au lieu d'utiliser, dites:

ssh remote.host my_command

Tu peux le faire:

ssh remote.host env ENV_VAR=$ENV_VAR my_command
pioto
la source
"Probablement"? J'aimerais lire cela avant d'essayer cette réponse. Cela n'a pas fonctionné pour moi.
Tishma
1
Voulez-vous préciser les erreurs reçues, etc.?
Pioto
1
@pioto Peut-être être cité, par exemple si ENV_VAR contient des espaces
Martin C. Martin
Sur Mac, vous devez avoir l'option -t pour une version interactive, sinon elle semble bloquée. Donc, ceci pourrait fonctionner: $ ssh -t remote.host env ENV_VAR = $ ENV_VAR ma_commande
muenalan
3

La réponse de @ emptyset (qui n'a pas fonctionné pour moi) m'a amenée à cette réponse:

Vous pouvez ajouter cette commande à votre ~/.ssh/authorized_keysfichier:

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

export VARIABLE=<something>a été immédiatement fermé et la connexion SSH a été fermée (me verrouillant hors du serveur), alors que /usr/bin/env ... $SHELLvotre shell par défaut exécutera un environnement modifié.

madprog
la source
Cela se bloque lorsque vous vous connectez pour moi. Lorsque je le supprime, SSH revient à la normale et j'obtiens mon shell de connexion habituel.
Nick Sweeting
@ NickSweeting avez-vous essayé peut-être de remplacer $SHELLpar un shell réel? Vérifiez également que / usr / bin / env existe sur le serveur. Cependant, la solution n'est pas parfaite: j'ai remarqué qu'elle se bloquait lorsque je voulais utiliser scpune commande en ligne.
Madprog
Oui, c'était la première chose que j'ai essayée. Malheureusement, cela n'a jamais fonctionné, a fini par permettre PermitUserEnvironment yeset utiliser à la environment="..."place de command="...".
Nick Sweeting
Cela fonctionne bien pour moi.
M. Tao le
3

Sur votre client local, dans votre ~/.ssh/configvous pouvez ajouter SetEnv, par exemple

Host myhost
  SetEnv FOO=bar

Remarque: Vérifiez man ssh_config.

Ensuite, sur le serveur, assurez-vous d’autoriser le client à transmettre certaines variables d’environnement dans votre /etc/ssh/sshd_configfichier de configuration:

AcceptEnv LANG LC_* FOO BAR*

Remarque: Vérifiez man sshd_config.

Kenorb
la source
1

Vous pouvez essayer d'appeler une commande personnalisée, en supposant que vous avez la configuration de la connexion SSH sans mot de passe. Sur le serveur, éditez votre entrée ~ / .ssh / registered_keys qui correspond à la clé de votre client:

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

Regardez ce lien dans la section Commande forcée pour un peu plus de détails.

ensemble vide
la source
1
J'ai essayé ça, mais ça ne marche pas. Il exécute la commande et quitte, il n'y a donc pas de session interactive. Est-ce le comportement normal? Si c'est le cas, cela pourrait être utile si tout ce que vous voulez faire est de permettre à une clé spécifique de déclencher une commande spécifique, mais si vous souhaitez transmettre des informations utilisées dans une session (comme l'indique la question), elles sont inutiles à cette fin. . Il n'y a pas de session.
iconoclaste
1

Je construisais une version personnalisée d'OpenSSH pour un périphérique avec un fichier cramfs dans le répertoire de base et / etc (Cram FS est en lecture seule). ~ / .Ssh / environment ne fonctionnerait pas sans une reconstruction complète du système de fichiers, qui ont été déployés sur le terrain. périphériques (systèmes embarqués d'où l'utilisation de CRAMFS). Vous pouvez spécifier dans sshd_config l'emplacement du fichier authroized_keys mais, pour une raison quelconque, environment = ne fonctionne que pour les variables d'environnement dans ~ / .ssh / authroized_keys. Éditer le fichier / etc / profile n'était pas une option et je devais charger ssh dans un répertoire non standard. Dans session.c après child_set_env (... "MAIL" ...), ajoutez simplement les variables d'environnement dont vous avez besoin (c'est un hack que je connais ...), mais insérez simplement que quelqu'un a besoin d'environnements codés en dur pour une session si vous êtes. en compilant à partir des sources, vous pouvez le faire. TGI-FLOSS

Volonté
la source
0

juste une simple commande:

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