通过SSH执行远程主机的命令或脚本时,经常会出现找不到自定义环境变量的问题。但是,如果通过SSH登录远程主机,然后再执行相同的命令或脚本,那么此时执行又是成功的。两种相似的方法,得到的结果却截然不同,看起来很诡异的现象,根本原因在于这两种方式使用的bash模式不同!

1. 通过SSH登录后再执行命令和脚本

这种方式会使用Bash的interactive + login shell模式,这里面有两个概念需要解释:interactive和login。

login故名思义,即登陆,login shell是指用户以非图形化界面或者以ssh登陆到机器上时获得的第一个shell,简单些说就是需要输入用户名和密码的shell。因此通常不管以何种方式登陆机器后用户获得的第一个shell就是login shell。

interactive意为交互式,这也很好理解,interactive shell会有一个输入提示符,并且它的标准输入、输出和错误输出都会显示在控制台上。所以一般来说只要是需要用户交互的,即一个命令一个命令的输入的shell都是interactive shell。而如果无需用户交互,它便是non-interactive shell。通常来说如bash script.sh此类执行脚本的命令就会启动一个non-interactive shell,它不需要与用户进行交互,执行完后它便会退出创建的Shell。

在interactive + login shell模式中,Shell首先会加载/etc/profile文件,然后再尝试依次去加载下列三个配置文件之一,一旦找到其中一个便不再接着寻找:

  • ~/.bash_profile
  • ~/.bash_login
  • ~/.profile

2. 通过SSH直接执行远程命令和脚本

这种方式会使用Bash的non-interactive + non-login shell模式,它会创建一个shell,执行完脚本之后便退出,不再需要与用户交互。

no-login shell,顾名思义就是不是在登录Linux系统时启动的(比如你在命令行提示符上输入bash启动)。它不会去执行/etc/profile文件,而会去用户的HOME目录检查.bashrc并加载。

系统执行Shell脚本的时候,就是属于这种non-interactive shell。Bash通过BASH_ENV环境变量来记录要加载的文件,默认情况下这个环境变量并没有设置。如果有指定文件,那么Shell会先去加载这个文件里面的内容,然后再开始执行Shell脚本。

3. 结论

由此可见,如果要解决SSH远程执行命令时找不到自定义环境变量的问题,那么可以在登录用户的HOME目录的.bashrc中添加需要的环境变量。

4、示例

当登录之后,直接在某台远程主机:10.0.63.9上执行日期格式化的命令时,打印的是正确的,如下:

[root@dev-appserver2 ~]# buildTimeStamp=--27T16::47.291+:; buildTimeStampStr=$(date -d $buildTimeStamp "+%y%m%d%H%M%S"); echo $buildTimeStampStr

当在另外一台主机(10.0.251.216)上远程执行ssh命令时,打印的结果不正确(差了八个时区),如下:

[root@host---- ~]# cat sshtime
buildTimeStamp=--27T16::47.291+:; buildTimeStampStr=$(date -d $buildTimeStamp "+%y%m%d%H%M%S"); echo $buildTimeStampStr [root@host---- ~]# a=`cat sshtime `
[root@host---- ~]# echo $a
buildTimeStamp=--27T16::47.291+:; buildTimeStampStr=$(date -d $buildTimeStamp "+%y%m%d%H%M%S"); echo $buildTimeStampStr
[root@host---- ~]# ssh root@10.0.63.9 $a
root@10.0.63.9's password:

此时修改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---- ~]# ssh root@10.0.63.9 $a
root@10.0.63.9's password:

最新文章

  1. JSP连接MySQL数据库问题
  2. 软件开发学习笔记 <二>软件开发模型、Up、Rup、敏捷Up
  3. 安装opensuse的笔记-重庆linux开源组织
  4. Win10 VMware虚拟机无法打开内核设备“\\.\Global\vmx86“
  5. (DP6.1.4.2)POJ 1088 滑雪
  6. 第一天的CI笔记
  7. StructureMap Exception Code: 207 Internal exception while creating Instance '06fc8bd7-76db-47c1-8d71-31090a074f5e' of PluginType QIMS.Repository.IComStaffRepository. Check the inner exception for more
  8. js 截取字符串
  9. SICP阅读笔记(一)
  10. 网页制作之html基础学习1-简介
  11. 在 CentOS 上安装 Tomcat7
  12. AJAX应用【股票案例】
  13. JVM学习记录-类加载的过程
  14. Redis内存模型(2):存储细节
  15. Centos发布java的war包后,无法访问发布的工程
  16. Python代码转c#部分参考样例
  17. Pandas 基础(3) - 生成 Dataframe 的几种方式
  18. zeebe docker-compose 运行(包含monitor)
  19. RMAN备份与恢复总汇
  20. linux如何修改登录用户密码

热门文章

  1. PDA手持扫描资产标签,盘点完成后将数据上传到PC端,固定资产系统查看盘点结果
  2. 使用属性android:onClick,出现异常NoSuchMethodException
  3. Python 中translate()与replace()区别
  4. 云计算平台简介(App Engine)
  5. Objective-C-实例变量与属性的关系
  6. 毕向东_Java基础视频教程第19天_IO流(06~10)
  7. 《C语言程序设计现代方法》第4章 编程题
  8. 转:从BeagleBone谈AM335x硬件系统设计
  9. Httpwatch 工具介绍
  10. 【DDD】领域驱动设计实践 —— 框架实现
  11. OpenVPN client端配置文件详细说明(转)
  12. Autofac 简单示例
  13. javaIO操作之字节输入流--InputStream
  14. Linux下MySQL的数据文件存放位置
  15. There was a problem with the instance info replicator
  16. 查询sql 索引
  17. Linux内核分析——字符集总结与分析
  18. CF520E Pluses everywhere
  19. 基于Python的机器学习实战:AadBoost
  20. java string和int之间的相互转化