背景
某团队业务上云,购买了云上的 ECS ,通过 shell 命令启动 java 程序,如果直接在当前服务器运行没问题,如果通过另一台服务器 ssh 远程执行启动脚本就会报错, java版本不匹配。
sshpass -p"XXX" ssh -T root@XXX "cd /home/data/tools;sh api.sh start"
问题分析
这个问题一看就和 ECS 没啥关系,但是工单分配到我这,我就需要解决。
从问题来看,就是 java 版本问题,而在当前服务器执行没问题,远程执行同样脚本就有问题,说明应该和环境变量有关。于是我修改一下 api.sh
,在 start 函数中加入环境变量输出的脚本。
#启动方法
start(){
echo "env:" $JAVA_HOME
echo $(java -version)
nohup java XXX
}
通过输出信息验证我的猜想,通过ssh 远程执行时取到的 java home 和登录到服务器上时执行取到的不一样,一个取到的是 java8 ,一个是java11 。
解决方案
在使用 SSH 执行远程命令时,常见的问题之一是无法获取到远程服务器上的环境变量。这通常是因为在非交互式 SSH 会话中(如使用 ssh user@host command
的方式),远程服务器不会加载用户的 shell 配置文件(如 .bashrc
、.bash_profile
、.zshrc
等),因此可能无法访问环境变量。
-
- 显式加载环境文件 : 你可以在远程命令中显式加载环境变量文件,例如:ssh user@host 'source ~/.bashrc; echo $MY_ENV_VAR'这条命令会首先加载
.bashrc
,然后执行你的命令。
- 显式加载环境文件 : 你可以在远程命令中显式加载环境变量文件,例如:ssh user@host 'source ~/.bashrc; echo $MY_ENV_VAR'这条命令会首先加载
-
- 使用 bash -l -c : 可以使用
bash
的登录模式来执行命令:ssh user@host 'bash -l -c "echo $MY_ENV_VAR"'bash -l -c
会启动一个登录 shell,这样就会加载所有相关的配置文件。
- 使用 bash -l -c : 可以使用
-
- 确保环境变量在非交互式 shell 中可用 : 确保你需要的环境变量在非交互式 shell 中也能正确设置。你可以将这些变量放到
.bash_profile
或.profile
中,这样即使在非交互式 shell 中,这些变量也会被加载。
- 确保环境变量在非交互式 shell 中可用 : 确保你需要的环境变量在非交互式 shell 中也能正确设置。你可以将这些变量放到
-
- 传递环境变量 : 有时你可以通过 SSH 直接传递环境变量:ssh user@host 'MY_ENV_VAR=value; echo $MY_ENV_VAR'这样你就可以在命令行中设置临时环境变量。
-
- 使用
env
命令 : 你也可以通过env
命令来明确设置环境变量:ssh user@host 'env MY_ENV_VAR=value command'
- 使用