ssh'ing时,如何在服务器上设置一个随会话而变化的环境变量?


92

当我ssh进入服务器时,如何将环境变量从客户端传递到服务器?此环境变量在ssh的不同调用之间变化,因此我不想$HOME/.ssh2/environment每次执行ssh调用时都覆盖它。我怎样才能做到这一点?


2
您的问题需要更具体一些。
伊格纳西奥·巴斯克斯

3
这个问题对我来说很清楚。但是,在ssh手册页上,除了您修改〜/ .ssh2 / environment之外,除了登录后手动设置变量外,我看不到其他方法。
garyjohn

每次都是不同的变量吗?还是不同的值?
丹尼斯·威廉姆森


1
反之,因为它已经越来越流行了。年龄大一点也没关系。
kenorb 2015年

Answers:


110

当然,您可以在命令中设置环境变量,但是在引用时要格外小心:请记住,您的外壳程序将解析本地命令行,然后远程外壳程序将在其字符串上使用go收到。

如果希望变量在服务器上获得与客户端上相同的值,请尝试以下SendEnv选项:

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

不过,这需要服务器的支持。使用OpenSSH,必须在中授权变量名/etc/sshd_config

如果服务器仅允许使用某些特定的变量名,则可以解决该问题。例如,通用设置允许LC_*通过,您可以执行以下操作:

ssh -o SendEnv = LC_MYVAR server.example.com'MYVAR = $ LC_MYVAR; 未设置LC_MYVAR; 出口MYVAR;我的命令”

如果甚至LC_*都不选择,则可以在TERM环境变量中传递信息,该信息始终被复制(但是可能存在长度限制)。您仍然必须确保远程外壳程序不会将TERM变量限制为指定已知的终端类型。-t如果您不启动远程交互式Shell,请将选项传递给ssh。

env TERM =“额外信息:$ TERM” ssh -t server.example.com'MYVAR = $ {TERM%:*}; TERM = $ {TERM ## *:}; 出口MYVAR;我的命令”

另一种可能性是直接在命令中定义变量:

ssh -t server.example.com'导出MYVAR =“额外信息”; 我的命令”

因此,如果传递局部变量:

ssh -t server.example.com'导出MYVAR ='“'$ LOCALVAR'”'; 我的命令”

但是,请注意引号问题:变量的值将直接插值到在远程端执行的shell代码段中。上面的最后一个示例假定$LOCALVAR不包含任何单引号(')。


2
非常感谢,我很生气,愚蠢的LC_ *变量是在ssh上导出的,您的回答将我指引到了哪里。我只需要在〜/ .ssh / config中禁用它
akostadinov 2012年

1
我处于原始海报的状态,但是我要转发的变量是TERM,因此您的回答让我有些困惑。最近的OpenSSH版本是否已禁用此TERM自动转发功能?
Doub 2012年

1
@Doub默认是拒绝服务器端的所有环境变量,并根据管理员的需要输入AcceptEnv指令sshd_config。但TERM据我所知,这是经过特殊处理的,据我所知,无法在服务器端对其进行过滤(无论在任何配置设置下,它都是在Shell的环境中设置的)。您确定没有配置文件脚本覆盖它(例如/etc/profile~/.profile~/.bashrc)吗?
Gilles 2012年

2
@Gilles:我再次对其进行了测试,除非我将TERM明确添加到我的AcceptEnv指令中,否则不会传递TERM。我没有打开外壳程序,而是直接运行命令,例如:“ ssh -o SendEnv = TERM shell.example.com env”。这将打印所有环境变量,并且TERM仅在客户端的SendEnv和服务器的AcceptEnv中显示。如果我在AcceptEnv或SendEnv中运行“ ssh -o SendEnv = TERM shell.example.com echo \ $ {TERM}”,它会显示“哑”,我不确定它来自哪里(env甚至不在这种情况下,请列出TERM)。
Doub 2012年

7
@Doub哦,我明白了。TERM仅当客户端请求服务器分配tty时才发送该消息。如果远程没有终端,则传输将毫无用处TERM。指定命令时,如果要在远程端安装终端,则需要使用-t命令行选项(或RequestTTY中的~/.ssh/config)。
吉尔斯2012年

12

如果可以管理目标主机,则可以配置sshd以允许将本地环境变量传递到目标主机。

在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.

sshd配置通常位于 /etc/ssh/sshd_config


7
知道默认情况下将其设置为“ no”非常有用!
詹森(Jathanism)2013年

6

因此,在您的客户端上,您有一些环境变量,并且您希望该变量可用于远程命令吗?我认为没有办法让ssh神奇地传递它,但是您可能可以做这样的事情。而不是使用,说:

ssh remote.host my_command

你可以这样做:

ssh remote.host env ENV_VAR=$ENV_VAR my_command

“大概”?我希望在实际尝试此答案之前先阅读一下。没为我工作。
tishma

1
想详细说明收到的任何错误等吗?
pioto

1
@pioto可能会引用,例如,如果ENV_VAR中包含空格
Martin C. Martin

在Mac上,交互式版本必须具有-t选项,否则它会卡住。因此这可能起作用:$ ssh -t remote.host env ENV_VAR = $ ENV_VAR my_command
muenalan

3

@emptyset的响应(对我不起作用)使我得到以下答案:

您可以将此命令添加到~/.ssh/authorized_keys文件中:

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

export VARIABLE=<something>立即退出,并且SSH连接已关闭(将我锁定在服务器之外),而/usr/bin/env ... $SHELL将在修改后的环境下运行您的默认Shell。


为我登录时,这只是挂起。当我删除它时,SSH恢复正常,我得到了通常的登录外壳。
Nick Sweeting

@NickSweeting您是否尝试过用$SHELL实际的外壳代替?还要检查服务器上是否存在/ usr / bin / env。但是,该解决方案并不完美:我注意到当我想使用scp或使用内联命令时,它会挂起。
madprog

是的,那是我尝试的第一件事。不幸的是,它从未发挥作用,最终启用PermitUserEnvironment yes并使用environment="..."代替command="..."
Nick Sweeting

这对我来说很好。
陶先生

2

在本地客户端上,~/.ssh/config您可以添加SetEnv,例如

Host myhost
  SetEnv FOO=bar

注意:检查man ssh_config

然后在服务器上,确保允许客户端在/etc/ssh/sshd_config配置文件中传递某些环境变量:

AcceptEnv LANG LC_* FOO BAR*

注意:检查man sshd_config


1

假设您具有无密码的ssh登录设置,则可以尝试调用自定义命令。在服务器上,编辑与客户端密钥相对应的〜/ .ssh / authorized_keys条目:

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

有关更多详细信息,请参阅“ 强制命令 ”部分中的此链接


1
我试过了,但是没有用。它运行命令并退出,因此没有交互会话。这是正常行为吗?如果是这样,那么如果您只想允许特定键触发特定命令,这可能会很有用,但是如果您要传递会话中使用的信息(如问题所述),那么该信息就没有用了。没有会议。
iconoclast

1

我正在为在主目录和/ etc中带有cramfs的设备进行OpenSSH的自定义构建,因此,如果不重建整个FS,〜/ .ssh / environment将无法正常工作,并且这些文件已在现场部署设备(嵌入式系统,因此使用CRAMFS)。您可以在sshd_config中指定authroized_keys文件的位置,但是由于某些原因,environment =仅适用于〜/ .ssh / authroized_keys中的环境变量。编辑/ etc / profile不是一个选择,我不得不将ssh加载到非标准目录中。在session.c中child_set_env(...“ MAIL” ...)之后,只需添加您需要的环境变量(这是我所知道的一种技巧...),但是如果有人在会话中需要一些硬编码的env,从源代码编译,您可以执行此操作。TGI牙线


0

只是一个简单的命令:

ssh -t your_host_or_ip 'export some_var_name=whatever_you_want; bash'
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.