经过SSH执行远程主机的命令或脚本时,常常会出现找不到自定义环境变量的问题。可是,若是经过SSH登陆远程主机,而后再执行相同的命令或脚本,那么此时执行又是成功的。两种类似的方法,获得的结果却大相径庭,看起来很诡异的现象,根本缘由在于这两种方式使用的bash模式不一样!shell
这种方式会使用Bash的interactive + login shell模式,这里面有两个概念须要解释:interactive和login。bash
login故名思义,即登录,login shell是指用户以非图形化界面或者以ssh登录到机器上时得到的第一个shell,简单些说就是须要输入用户名和密码的shell。所以一般无论以何种方式登录机器后用户得到的第一个shell就是login shell。app
interactive意为交互式,这也很好理解,interactive shell会有一个输入提示符,而且它的标准输入、输出和错误输出都会显示在控制台上。因此通常来讲只要是须要用户交互的,即一个命令一个命令的输入的shell都是interactive shell。而若是无需用户交互,它即是non-interactive shell。一般来讲如bash script.sh
此类执行脚本的命令就会启动一个non-interactive shell,它不须要与用户进行交互,执行完后它便会退出建立的Shell。ssh
在interactive + login shell模式中,Shell首先会加载/etc/profile
文件,而后再尝试依次去加载下列三个配置文件之一,一旦找到其中一个便再也不接着寻找:ui
这种方式会使用Bash的non-interactive + non-login shell模式,它会建立一个shell,执行完脚本以后便退出,再也不须要与用户交互。spa
no-login shell,顾名思义就是否是在登陆Linux系统时启动的(好比你在命令行提示符上输入bash启动)。它不会去执行/etc/profile
文件,而会去用户的HOME目录检查.bashrc
并加载。命令行
系统执行Shell脚本的时候,就是属于这种non-interactive shell。Bash经过BASH_ENV
环境变量来记录要加载的文件,默认状况下这个环境变量并无设置。若是有指定文件,那么Shell会先去加载这个文件里面的内容,而后再开始执行Shell脚本。code
因而可知,若是要解决SSH远程执行命令时找不到自定义环境变量的问题,那么能够在登陆用户的HOME目录的.bashrc
中添加须要的环境变量。server
当登陆以后,直接在某台远程主机:10.0.63.9上执行日期格式化的命令时,打印的是正确的,以下:blog
[root@dev-appserver2 ~]# buildTimeStamp=2017-09-27T16:58:47.291+08:00; buildTimeStampStr=$(date -d $buildTimeStamp "+%y%m%d%H%M%S"); echo $buildTimeStampStr 170927165847
当在另一台主机(10.0.251.216)上远程执行ssh命令时,打印的结果不正确(差了八个时区),以下:
[root@host-10-0-251-216 ~]# cat sshtime buildTimeStamp=2017-09-27T16:58:47.291+08:00; buildTimeStampStr=$(date -d $buildTimeStamp "+%y%m%d%H%M%S"); echo $buildTimeStampStr [root@host-10-0-251-216 ~]# a=`cat sshtime ` [root@host-10-0-251-216 ~]# echo $a buildTimeStamp=2017-09-27T16:58:47.291+08:00; buildTimeStampStr=$(date -d $buildTimeStamp "+%y%m%d%H%M%S"); echo $buildTimeStampStr [root@host-10-0-251-216 ~]# ssh root@10.0.63.9 $a root@10.0.63.9's password: 170927085847
此时修改10.0.63.9上,root根目录下的.bashrc文件,增长TZ的设置,再次执行ssh打印的结果是正确的:
[root@dev-appserver2 ~]# cat .bashrc # .bashrc # User specific aliases and functions alias rm='rm -i' alias cp='cp -i' alias mv='mv -i' export TZ="Asia/Shanghai" # Source global definitions if [ -f /etc/bashrc ]; then . /etc/bashrc fi [root@dev-appserver2 ~]#
[root@host-10-0-251-216 ~]# ssh root@10.0.63.9 $a root@10.0.63.9's password: 170927165847