本文的情况,不同的linux系统版本,表现可能不同。

问题:默认情况下,paramiko在远程主机上执行命令的时候,命令的搜索路径为(/usr/local/bin:/bin:/usr/bin),这样我们安装的软件,如果命令不在这些路径下的话,就会执行错误,报找不到命令的错误

解决办法:

  1. 就是在上面的路径里(/usr/local/bin:/bin:/usr/bin)加我们需要命令的软链接(ln /usr/install/jdk1.8.0_60/bin/java -s java)
  2. 把需要的路径包含进去 stdin, stdout, stderr = ssh.exec_command('export PATH=$PATH:/usr/local/install/xxx/;echo $PATH')
  3. 先执行一条命令 stdin, stdout, stderr = ssh.exec_command('. ~/.bashrc;echo $PATH');stdin, stdout, stderr = ssh.exec_command('source ~/.bashrc;bash test.sh')
  4. 方法2和3,环境变量可以传到后续执行的‘.sh’脚本里面去
  5. paramiko的ssh.exec_command()命令会开启一个单独的session,而且在exec_command中设定的环境变量不会传递给后续的脚本。解决方法是使用bash执行命令:ssh.exec_command("bash -l -c 'some commands and some scripts...'")

  bash -l -c解释:-l(login)表示bash作为一个login shell;-c(command)表示执行后面字符串内的命令,这样执行的脚本,可以获取到/etc/profile里的全局变量,包括我们搜索命令的目录PATH

  • -l Make bash act as if it had been invoked as a login shell
  • -c If the -c option is present, then commands are read from string.
  • You're running the command passed to the -c argument. -l makes it a login shell so bash first reads /etc/profile,

遗留问题:为什么paramiko登录后,只获得路径(/usr/local/bin:/bin:/usr/bin)

解答:密码存在于被连接机器的/etc/ssh/sshd_config配置文件里;如下所示,sshd服务默认把(/usr/local/bin:/bin:/usr/bin)作为PATH的值

#       $OpenBSD: sshd_config,v 1.80 // :: djm Exp $

# This is the sshd server system-wide configuration file.  See
# sshd_config() for more information. # This sshd was compiled with PATH=/usr/local/bin:/bin:/usr/bin # The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented. Uncommented options change a
# default value.

对于上面的SSHD默认PATH值,不同的Op'e'nBOpenBSD不一样

#       $OpenBSD: sshd_config,v 1.101 // :: djm Exp $

   # This is the sshd server system-wide configuration file.  See
# sshd_config() for more information. # This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin # The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented. Uncommented options override the

再说一个实际验证的结论:

ssh -T admin@10.x.x.x 'echo $PATH' 获得什么环境变量呢?

-T 表示不使用伪终端(man -a ssh---->  -T      Disable pseudo-terminal allocation.)

那么没有伪终端的话,获得什么样的PATH呢(其他环境变量类似)?

首先,通过上面的知识可知,SSHD是有个默认PATH值的,编译到SSHD(ssh_server)的代码里的(SSHD可能是C语音写的吧);

其次,不使用伪终端登录后,首先执行的用户目录下的bashrc脚本(~/.bashrc),一般bashrc脚本里面会执行脚本/etc/profile或者/etc/bashrc之类的;总之只要被bashrc执行产生的全局变量(export)都会传递到后续的脚本或者命令行里

上一步需要注意的一点就是,sshd即ssh_server必须使用bash作为登录shell,而不是zsh等其他的shell(我以为如果登录shell是zsh,会执行~/.zshrc,结果发现我错了),如果使用的zsh,发现只读到写死到sshd_server里面的PATH值

我本机测试的结果是,下面三种情况,都只能读取sshd_server写死的环境变量

stdin, stdout, stderr = ssh.exec_command('echo $PATH')和stdin, stdout, stderr = ssh.exec_command('echo $PATH',get_pty=True)和stdin, stdout, stderr = ssh.exec_command('echo $PATH',get_pty=False)

get_pty表示是否分配伪终端

paramiko中关于伪终端pty的定义和描述

@open_only
def get_pty(self, term='vt100', width=80, height=24, width_pixels=0,
height_pixels=0):
"""
Request a pseudo-terminal from the server. This is usually used right
after creating a client channel, to ask the server to provide some
basic terminal semantics for a shell invoked with `invoke_shell`.
It isn't necessary (or desirable) to call this method if you're going
to execute a single command with `exec_command`. :param str term: the terminal type to emulate
(for example, ``'vt100'``)
:param int width: width (in characters) of the terminal screen
:param int height: height (in characters) of the terminal screen
:param int width_pixels: width (in pixels) of the terminal screen
:param int height_pixels: height (in pixels) of the terminal screen :raises:
`.SSHException` -- if the request was rejected or the channel was
closed
"""
m = Message()
m.add_byte(cMSG_CHANNEL_REQUEST)
m.add_int(self.remote_chanid)
m.add_string('pty-req')
m.add_boolean(True)
m.add_string(term)
m.add_int(width)
m.add_int(height)
m.add_int(width_pixels)
m.add_int(height_pixels)
m.add_string(bytes())
self._event_pending()
self.transport._send_user_message(m)
self._wait_for_event()

  伪终端不是真实的终端,我们登录unix界面,然后在里面启动终端,这属于真实的终端,假如我们直接通过ssh协议连接sshd(ssh admin@ip),这样建立的就是伪终端。所以说伪终端不是真实的物理终端,但是却具有真实终端的函数和功能。伪终端是由类似于xterm的终端模拟器创建的。

  在unix系统中,大量的进程和I/O函数在控制终端中运行。伪终端可以处理控制字符(^C)

   为什么使用pseudo-terminal就能终止远程进程呢?

  当SSH链接关闭,远程服务器会关闭pty,同时发送SIGHUP信号来终止远程执行的命令。

SIGHUP is sent to the controlling process (session leader) associated with a controlling terminal if a disconnect is detected by the terminal interface.

参考:

1、http://feihu.me/blog/2014/env-problem-when-ssh-executing-command-on-remote/

2、https://gist.github.com/yegle/1564928

paramiko获取远程主机的环境变量的更多相关文章

  1. python获取自己的环境变量

    1. import sys sys.path 2. from distutils.sysconfig import get_python_lib get_python_lib() 3. import ...

  2. U-BOOT分析之:环境变量

    (环境如下:U-BOOT  S3C2440  LINUX) 记录自己的学习过程,如果分析有问题,请帮忙指正. 最近在研究U-BOOT的代码,其中的环境变量个人觉得用处非常大,所以重点学习和分析一下. ...

  3. 【linux草鞋应用编程系列】_2_ 环境变量和进程控制

    一. 环境变量     应用程序在执行的时候,可能需要获取系统的环境变量,从而执行一些相应的操作.     在linux中有两种方法获取环境变量,分述如下.   1.通过main函数的参数获取环境变量 ...

  4. Java起源、发展历程、环境变量、第一个Java程序等【1】

    若有不正之处,请多多谅解并欢迎批评指正,不甚感激. 请尊重作者劳动成果,转载请标明原文链接: 本文原创作者:pipi-changing 本文原创出处:http://www.cnblogs.com/pi ...

  5. linux环境变量(转)

    转自: http://www.cnblogs.com/growup/archive/2011/07/02/2096142.html Linux 的变量可分为两类:环境变量和本地变量 环境变量 或者称为 ...

  6. (转载)linux环境变量

    转自:http://www.cnblogs.com/growup/archive/2011/07/02/2096142.html Linux 的变量可分为两类:环境变量和本地变量 环境变量,或者称为全 ...

  7. 解析docker中的环境变量使用和常见问题解决

    docker容器中的环境变量 docker可以为容器配置环境变量.配置的途径有两种: 在制作镜像时,通过ENV命令为镜像增加环境变量.在容器启动时使用该环境变量. 在容器启动时候,通过参数配置环境变量 ...

  8. Linux中环境变量中文件执行顺序

        Linux 的变量可分为两类:环境变量和本地变量   环境变量:或者称为全局变量,存在于所有的shell 中,在你登陆系统的时候就已经有了相应的系统定义的环境变量了.Linux 的环境变量具有 ...

  9. Java用System读取系统相关信息、环境变量——(六)

    package Java_Test; public class System1 { public static void main(String[] args) { // TODO Auto-gene ...

随机推荐

  1. BZOJ 4479: [Jsoi2013]吃货jyy

    一句话题意:求必须包含某K条边的回路(回到1),使得总权值最小 转化为权值最小的联通的偶点 令F[i]表示联通状态为i的最小权值,(3^n状压)表示不在联通块内/奇点/偶点,连边时先不考虑必选的边的度 ...

  2. kafka消息的可靠性

    本文来自网易云社区 作者:田宏增 Kafka的高可靠性的保障来源于其健壮的副本(replication)策略.通过调节其副本相关参数,可以使得Kafka在性能和可靠性之间运转的游刃有余.Kafka从0 ...

  3. [python][oldboy]字符串 format

    #coding=utf8 def format(self, *args, **kwargs): # known special case of str.format """ ...

  4. Oracle 用户和权限

    Oracle 用户和权限Oracle 中,一般不会轻易在一个服务器上创建多个数据库,在一个数据库中,不同的项目由不同的用户访问,每一个用户拥有自身创建的数据库对象,因此用户的概念在 Oracle中非常 ...

  5. oracle dual表用途及结构详解

    dual是一个虚拟表,用来构成select的语法规则,oracle保证dual里面永远只有一条记录.我们可以用它来做很多事情,如下: 1.查看当前用户,可以在 SQL Plus中执行下面语句 sele ...

  6. 【bzoj3505】[Cqoi2014]数三角形 容斥原理

    题目描述 给定一个nxm的网格,请计算三点都在格点上的三角形共有多少个.下图为4x4的网格上的一个三角形. 注意三角形的三点不能共线. 输入 输入一行,包含两个空格分隔的正整数m和n. 输出 输出一个 ...

  7. 刷题总结——树的同构(bzoj4337 树上hash)

    Description 树是一种很常见的数据结构. 我们把N个点,N-1条边的连通无向图称为树. 若将某个点作为根,从根开始遍历,则其它的点都有一个前驱,这个树就成为有根树. 对于两个树T1和T2,如 ...

  8. bzoj 1758 [Wc2010]重建计划 分数规划+树分治单调队列check

    [Wc2010]重建计划 Time Limit: 40 Sec  Memory Limit: 162 MBSubmit: 4345  Solved: 1054[Submit][Status][Disc ...

  9. 【CF1028A】Find Square(签到)

    题意:给定矩阵里,找到由B构成的矩形的中心 n,m<=115 思路: #include<cstdio> #include<cstring> #include<str ...

  10. sublime flatLand 主题

    今天试了下感觉主题不错 记下来备忘. 1.sublime3 package control install  搜索 flatLand 2 安装完成后. 修改 Preferences 文件,通过 Sub ...