【问题标题】:Some Unix commands fail with "<command> not found", when executed using Python Paramiko exec_command使用 Python Paramiko exec_command 执行时,某些 Unix 命令失败并显示“<command> not found”
【发布时间】:2021-08-07 05:02:09
【问题描述】:

我正在尝试在 Paramiko exec_command 的帮助下从 Python 在 Unix 服务器中运行 sesu 命令。但是,当我运行此命令 exec_command('sesu test') 时,我得到了

sh: sesu: 未找到

当我运行简单的ls 命令时,它会给我想要的输出。只有使用sesu 命令才能正常工作。

这就是我的代码的样子:

import paramiko

host = host
username = username
password = password
port = port

ssh=paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(ip,port,username,password)
stdin,stdout,stderr=ssh.exec_command('sesu test')
stdin.write('Password')
stdin.flush()
outlines=stdout.readlines()
resp=''.join(outlines)
print(resp)

【问题讨论】:

    标签: python shell ssh paramiko


    【解决方案1】:

    SSHClient.exec_command 默认情况下不会在“登录”模式下运行 shell,也不会为会话分配伪终端。因此,与您的常规交互式 SSH 会话相比(特别是对于非交互式会话,.bash_profile 没有来源),因此(可能)获取了一组不同的启动脚本。和/或脚本中的不同分支基于TERM 环境变量的缺失/存在。

    可能的解决方案(按优先顺序):

    1. 修复命令不依赖于特定环境。在命令中使用sesu 的完整路径。例如:

       /bin/sesu test
      

      如果您不知道完整路径,在常见的 *nix 系统上,您可以在交互式 SSH 会话中使用 which sesu 命令。

    2. 修复您的启动脚本,为交互式和非交互式会话设置相同的 PATH

    3. 尝试通过登录 shell 显式运行脚本(将--login 开关与常见的 *nix shell 一起使用):

       bash --login -c "sesu test"
      
    4. 如果命令本身依赖于特定的环境设置并且您无法修复启动脚本,您可以在命令本身中更改环境。其语法取决于远程系统和/或 shell。在常见的 *nix 系统中,这是有效的:

       PATH="$PATH;/path/to/sesu" && sesu test
      
    5. 另一种(不推荐)方法是使用get_pty 参数强制为“exec”通道分配伪终端:

       stdin,stdout,stderr=ssh.exec_command('sesu test', get_pty=True)
      

      使用伪终端自动执行命令会给您带来令人讨厌的副作用。参见例如Is there a simple way to get rid of junk values that come when you SSH using Python's Paramiko library and fetch output from CLI of a remote machine?


    LD_LIBRARY_PATH 和定位共享对象可能存在类似问题。


    另见:

    【讨论】:

    • 你应该推荐command -V而不是whichwhich 完全错误的系统已经不多了。但既然有安全的 POSIX 替代品,为什么还要冒险呢?