zoukankan      html  css  js  c++  java
  • 解决SSH远程执行命令找不到环境变量的问题

    通过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=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
  • 相关阅读:
    静态构造函数(C# 编程指南)
    SQL SERVER2008 存储过程、表、视图、函数的权限
    EF架构~为EF DbContext生成的实体添加注释 【转】
    WebBrowser 多线程问题,寻求解答!(已经搞清楚!) 【转】
    EF架构~将数据库注释添加导入到模型实体类中 【转】
    window.name web开发iframe 跨域间的值传输问题
    javascript 验证 国际格式 电话号码
    认识HTML5的WebSocket
    Jquery 滚屏
    哎 为了自己的生活能过的去 从今天起开始写技术博客 请大家多多指教
  • 原文地址:https://www.cnblogs.com/zhenyuyaodidiao/p/9287497.html
Copyright © 2011-2022 走看看