使用Python Paramiko的exec_command执行某些Unix命令时,会出现“<command> not found”的错误

6
我试图使用Paramiko的exec_command从Python在Unix服务器上运行sesu命令。然而,当我运行这个命令exec_command('sesu test')时,我得到以下错误信息:

sh: sesu: not found

当我运行简单的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)
1个回答

17

默认情况下,SSHClient.exec_command 不以“登录”模式运行 shell,并且不为会话分配伪终端。因此,可能使用了不同的启动脚本(尤其是对于非交互式会话,未必会使用.bash_profile)。根据 TERM 环境变量存在/不存在的情况,也可能采用脚本中不同的分支。

可能的解决方案(按首选顺序):

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

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

    修复启动脚本以使交互和非交互会话的PATH设置相同。

    尝试通过登录Shell显式运行脚本(在常见的*nix shell中使用--login开关):
    bash --login -c "sesu test"
    
  2. 如果命令本身依赖于特定的环境设置,而您无法修复启动脚本,您可以在命令本身中更改环境。语法取决于远程系统和/或shell。在通用的*nix系统中,可以这样做:

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

  5. stdin,stdout,stderr = ssh.exec_command('sesu test', get_pty=True)
    
    使用伪终端自动化命令执行可能会带来讨厌的副作用。例如,参见使用Python的Paramiko库进行SSH并从远程机器的CLI获取输出时如何消除垃圾值的简单方法?

您可能在LD_LIBRARY_PATH和定位共享对象方面遇到类似的问题。


另请参阅:


你应该推荐使用 command -V 而不是 which。现在已经很少有系统会出现 which 完全错误的情况了,但既然有一个安全的 POSIX 替代品,为什么要冒险呢? - tripleee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接