ssh'ing 时,如何在服务器上设置一个从会话到会话更改的环境变量?

Ros*_*ers 122 ssh environment-variables

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

Gil*_*il' 140

当然,您可以在命令中设置环境变量,但是您必须小心引用:请记住,您的 shell 将解析您的本地命令行,然后远程 shell 将对它的字符串进行处理收到。

如果您希望变量在服务器上获得与客户端上相同的值,请尝试以下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;我的命令'

如果 evenLC_*不是一个选项,您可以在TERM环境变量中传递信息,该变量总是被复制(但是可能有长度限制)。您仍然需要确保远程 shell 不会限制TERM变量来指定已知的终端类型。-t如果您没有启动远程交互式 shell,请将选项传递给 ssh。

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

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

ssh -t server.example.com 'export MYVAR="额外信息"; 我的命令'

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

ssh -t server.example.com 'export MYVAR='"'$LOCALVAR'"'; 我的命令'

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

  • @Doub 哦,我明白了。`TERM` 仅在客户端请求服务器分配 tty 时传输。如果远程端没有终端,则传输“TERM”将毫无用处。当你指定一个命令时,如果你想在远程端有一个终端,你需要`-t`命令行选项(或`~/.ssh/config`中的`RequestTTY`)。 (7认同)
  • 非常感谢,我对在 ssh 上导出愚蠢的 LC_* 变量感到愤怒,而您的回答将我指向何处。我只需要在 ~/.ssh/config 中禁用它 (2认同)
  • @Gilles:我再次测试了它,除非我明确地将 TERM 添加到我的 AcceptEnv 指令中,否则不会传递 TERM。我没有打开shell,而是直接运行命令,例如:“ssh -o SendEnv=TERM shell.example.com env”。这会打印所有环境变量,并且 TERM 仅在客户端上的 SendEnv 和服务器上的 AcceptEnv 中时才会出现。如果我在没有 AcceptEnv 或 SendEnv 的情况下运行“ssh -o SendEnv=TERM shell.example.com echo \${TERM}”,它会打印“dumb”,我不确定它来自哪里(env 甚至不在这种情况下列出 TERM)。 (2认同)

小智 18

如果您可以管理目标主机,则可以配置 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.
Run Code Online (Sandbox Code Playgroud)

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

  • 知道默认设置为“否”非常有用! (8认同)

ken*_*orb 12

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

Host myhost
  SetEnv FOO=bar
Run Code Online (Sandbox Code Playgroud)

注意:检查man ssh_config.

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

AcceptEnv LANG LC_* FOO BAR*
Run Code Online (Sandbox Code Playgroud)

注意:检查man sshd_config.

  • 值得注意的是,特别是因为 OP 要求将其设置为不同的“会话到会话”,与所有 `ssh_config` 选项一样,它也可以通过标志设置:`ssh -o 'SetEnv FOO=bar BAR=foo' [ ...]`。(如果设置多个变量,它们必须提供给单个 `-o 'SetEnv`。) (2认同)

小智 7

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

ssh remote.host my_command
Run Code Online (Sandbox Code Playgroud)

你可以这样做:

ssh remote.host env ENV_VAR=$ENV_VAR my_command
Run Code Online (Sandbox Code Playgroud)

  • “大概”?我希望在实际尝试这个答案之前先读一下。不适合我。 (2认同)

小智 5

@emptyset 的回应(对我来说不起作用)让我得到了这个答案:

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

command="/usr/bin/env VARIABLE=<something> $SHELL" ssh-rsa <key>
Run Code Online (Sandbox Code Playgroud)

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


emp*_*set 1

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

command="export VARIABLE=<something>" ssh-rsa <key>
Run Code Online (Sandbox Code Playgroud)

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