当前位置:
文档之家› ssh连接远程主机执行脚本的环境变量问题
ssh连接远程主机执行脚本的环境变量问题
END IF END IF
为了验证这个过程,我们来做一些测试。首先设计每个配置文件的内容如下:
1 user@remote > cat /etc/profile 2 echo @ /etc/profile 3 user@remote > cat ~/.bash_profile 4 echo @ ~/.bash_profile 5 user@remote > cat ~/.bash_login 6 echo @ ~/.bash_login
说明,本文所使用的机器是:SUSE Linux Enterprise。
问题定位
这看起来像是环境变量引起的问题,为了证实这一猜想,我在这条命令之前加了一句: which app ,来查看app的安装路径。在remote本机上执行 脚本时,它会打印出app正确的安装路径。但再次用ssh来执行时,却遇到下面的错误:
~/myscript.sh: line n: app: command not found
app是一个新安装的程序,安装路径明明已通过 /etc/profile 配置文件加到环境变量中,但这里为何会找不到?如果直接登陆机器remote并执 行 ~/myscript.sh 时,app程序可以找到并顺利执行。但为什么使用了ssh远程执行同样的脚本就出错了呢?两种方式执行脚本到底有何不同?如果 你也心存疑问,请跟随我一起来展开分析。
下面给出这个加载过程的伪代码:
execute /etc/profile IF ~/.bash_profile exists THEN
execute ~/.bash_profile ELSE
IF ~/.bash_login exist THEN execute ~/.bash_login
ELSE IF ~/.profile exist THEN execute ~/.profile END IF
那么此模式最简单的两个例子为:
用户直接登陆到机器获得的第一个shell 用户使用 ssh user@remote 获得的shell
加载配置文件
这种模式下,shell首先加载 /etc/profile ,然后再尝试依次去加载下列三个配置文件之一,一旦找到其中一个便不再接着寻找:
~/.bash_profile ~/.bash_login ~/.profile
前面说过,使用ssh也会得到一个login shell,所以如果在另外一台机器上运行 ssh user@remote 时h要弄得这么复杂?每个配置文件存在的意义是什么?
/etc/profile 很好理解,它是一个全局的配置文件。后面三个位于用户主目录中的配置文件都针对用户个人,也许你会问为什么要有这么多,只 用一个 ~/.profile 不好么?究竟每个文件有什么意义呢?这是个好问题。
If command is specified, it is executed on the remote host instead of a login shell.
这说明在指定命令的情况下,命令会在远程主机上执行,返回结果后退出。而未指定时,ssh会直接返回一个登陆的shell。但到这里还是无法理 解,直接在远程主机上执行和在返回的登陆shell中执行有什么区别?即使在远程主机上执行不也是通过shell来执行的么?难道是这两种方式使用的 shell有什么不同?
interactive意为交互式,这也很好理解,interactive shell会有一个输入提示符,并且它的标准输入、输出和错误输出都会显示在控制台上。所以一般 来说只要是需要用户交互的,即一个命令一个命令的输入的shell都是interactive shell。而如果无需用户交互,它便是noninteractive shell。通常来 说如 bash script.sh 此类执行脚本的命令就会启动一个noninteractive shell,它不需要与用户进行交互,执行完后它便会退出创建的shell。
2015/6/15
user@local > ssh user@remote user@remote> ~/myscript.sh
ssh连接远程主机执行脚本的环境变量问题
# 先远程登陆到remote上 # 然后在返回的shell中执行脚本
结果竟然成功了。那么ssh以这两种方式执行的命令有何不同?带着这个问题去查询了 man ssh :
进入这个新的login shell,便会得到以下输出:
@ /etc/profile @ /home/user/.bash_profile
果然与文档一致,bash首先会加载全局的配置文件 /etc/profile ,然后去查找 ~/.bash_profile ,因为其已经存在,所以剩下的两个文件不再会被 查找。
目录
问题定位 bash的四种模式
interactive + login shell 加载配置文件 配置文件的意义
noninteractive + login shell interactive + nonlogin shell
加载配置文件 bashrc VS profile noninteractive + nonlogin shell 加载配置文件 更为直观的示图 典型模式总结 再次尝试 配置文件建议 写在结尾
data:text/html;charset=utf8,%3Ch1%20class%3D%22posttitle%22%20style%3D%22color%3A%20rgb(34%2C%2034%2C%2034)%3B%20margin%3A%200px%3B%20lineheight%3A%201.1%3B%20fontsize%3A%2030px%… 2/8
One advantage of bash’s ability to look for either synonym is that you can retain your .profile if you have been using the Bourne shell. If you need to add bashspecific commands, you can put them in .bash_profile followed by the command source .profile. When you log in, all the bashspecific commands will be executed and bash will source .profile, executing the remaining commands. If you decide to switch to using the Bourne shell you don’t have to modify your existing files. A similar approach was intended for .bash_login and the C shell .login, but due to differences in the basic syntax of the shells, this is not a good idea.
which: no app in (/usr/bin:/bin:/usr/sbin:/sbin)
这很奇怪,怎么括号中的环境变量没有了 app 程序的安装路径?不是已通过 /etc/profile 设置到 PATH 中了?再次在脚本中加入 echo $PATH 并以 ssh执行,这才发现,环境变量仍是系统初始化时的结果:
暂时还没有头绪,但隐隐感到应该与shell有关。因为我通常使用的是 bash ,所以又去查询了 man bash ,才得到了答案。
bash的四种模式
在man page的INVOCATION一节讲述了 bash 的四种模式, bash 会依据这四种模式而选择加载不同的配置文件,而且加载的顺序也有所不同。本 文ssh问题的答案就存在于这几种模式当中,所以在我们揭开谜底之前先来分析这些模式。
/usr/bin:/bin:/usr/sbin:/sbin
这证明 /etc/profile 根本没有被调用。为什么?是ssh命令的问题么?
随后我又尝试了将上面的ssh分解成下面两步:
data:text/html;charset=utf8,%3Ch1%20class%3D%22posttitle%22%20style%3D%22color%3A%20rgb(34%2C%2034%2C%2034)%3B%20margin%3A%200px%3B%20lineheight%3A%201.1%3B%20fontsize%3A%2030px%… 1/8
@ /etc/profile @ /home/user/.profile
~/.profile 终于熬出头,得见天日。通过以上三个实验,配置文件的加载过程得到了验证,除去 /etc/profile 首先被加载外,其余三个文件的加 载顺序为: ~/.bash_profile > ~/.bash_login > ~/.profile ,只要找到一个便终止查找。
接下来移除 ~/.bash_profile ,启动login shell得到结果如下:
@ /etc/profile @ /home/user/.bash_login
因为没有了 ~/.bash_profile 的屏蔽,所以 ~/.bash_login 被加载,但最后一个 ~/.profile 仍被忽略。 再次移除 ~/.bash_login ,启动login shell的输出结果为:
interactive + login shell
第一种模式是交互式的登陆shell,这里面有两个概念需要解释:interactive和login:
login故名思义,即登陆,login shell是指用户以非图形化界面或者以ssh登陆到机器上时获得的第一个shell,简单些说就是需要输入用户名和密码的 shell。因此通常不管以何种方式登陆机器后用户获得的第一个shell就是login shell。