假设我有两台主机:A 和 B,分别有用户 a 和 b。B 是安装了 Cygwin 的 Windows 机器(如果这很重要的话)。
B 配置为从 A 通过 SSH 无需密码访问(它包含 A 的公共 RCA 密钥),因此我可以通过以下方式从 A 在其上运行命令:
ssh b@B [command]
但是当我尝试运行需要访问环境变量的命令时,该命令失败:
[15:54:08] - a@A - ~
$ ssh b@B 'echo $ANT_HOME'
返回空字符串。
相同的命令,如果直接连接(不是通过 SSH)则可以正确执行:
b@B ~
$ echo $ANT_HOME
/cygdrive/c/PROGRA~1/apache-ant-1.9.0
后者是可能的,因为相关变量已在“bash_profile”中导出:
export JAVA_HOME="/cygdrive/c/PROGRA~1/Java/jdk1.7.0_45"
export ANT_HOME="/cygdrive/c/PROGRA~1/apache-ant-1.9.0"
但由于某种原因,这不适用于 SSH 情况。
一些可能有用的附加信息。
主机 B 有 Windows XP + Cygwin。CYGWIN sshd 在 SYSTEM 帐户下运行。JAVA_HOME 和 ANT_HOME 在 Windows 的“系统”环境变量部分中定义。
当我运行“$ ssh b@B env”命令时,它不会打印 ANT_HOME 或 JAVA_HOME,但如果我将它们包含在 sshd_config 文件中,它就会打印。但即便如此,简单的命令 ssh b@B 'echo $ANT_HOME' 也无法像我预期的那样工作。
请提示我通过 SSH 运行命令需要做什么。
答案1
从我的服务器的手册页中:
- 如果文件 ~/.ssh/environment 存在,则读取该文件,并允许用户更改其环境。请参阅 sshd_config(5) 中的 PermitUserEnvironment 选项。
您需要声明环境变量并允许它们在远程服务器位置/etc/ssh/sshd_config
,通过启用属性 PermitUserEnvironmentPermitUserEnvironment yes
并在 ~/.ssh/environment 中设置您的环境变量。
答案2
当您将命令作为 ssh 的参数运行时,该命令由 sshd 直接运行;不涉及 shell。
您可以使用如下方法验证这一点:
ssh b@B pstree
shell(本例中为 bash)会拉入您的 .bash_profile,并且只有在 shell 作为登录 shell 调用时,或者使用 --login 选项调用 shell 时才会这样做(请参阅 bash 手册页;查找 INVOCATION)。直接运行命令时获得的环境由登录时 sshd 和 PAM 等设置。
因此,如果您想要您的 .bash_profile,您需要在 shell 下运行它,并且您需要将 shell 作为交互式或登录 shell 运行,如下所示:
ssh b@B "bash -l -c 'env'"
这应该会得到你想要的输出。唯一要注意的是引用很快就会变得棘手。请注意,至少在 Linux 上,
ssh b@B bash -l -c 'env'
不会为您提供登录 shell(我不确定为什么)。
答案3
如果您不想弄乱 SSH 配置,只想启动程序,那么请在本地创建一个脚本,定义变量并运行该程序。现在,scp
运行该脚本ssh
。
> cat <<EOF >run.sh
X=42 program
EOF
> scp user@host run.sh user@host:path/to/target/ || exit
> ssh user@host "cd path/to/target/; bash run.sh"
现在在另一台机器上的program
环境变量下启动X=42
。在 Linux 下,这可以完美运行,但是对于 Cygwin,路径bash
可能缺失。但重点是您可以通过这种方式隧道传输环境变量。