在python脚本中通过ssh执行哪个命令

在python脚本中通过ssh执行哪个命令,python,bash,ssh,Python,Bash,Ssh,我试图在Python脚本中通过SSH运行命令,该命令是solsql 我认为问题在于ssh命令,而不是Python部分,但可能两者都有 我试过了 subprocess.check_output("ssh root@IP which solsql", stderr=subprocess.STDOUT, shell=True) 但是我犯了一个错误 我尝试手动运行该命令: ssh root@{server_IP}" which solsql" 我得到了不同的输出 在服务器上,我得到了真正的路

我试图在Python脚本中通过SSH运行命令
,该命令是solsql

我认为问题在于
ssh
命令,而不是Python部分,但可能两者都有

我试过了

subprocess.check_output("ssh root@IP which solsql",
    stderr=subprocess.STDOUT, shell=True)
但是我犯了一个错误

我尝试手动运行该命令:

ssh root@{server_IP}" which solsql"
我得到了不同的输出

在服务器上,我得到了真正的路径(
/opt/solidDB/solidDB-6.5/bin/solsql
) 但通过SSH,我得到了以下信息:

which: no solsql in
(/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin)

我想你在找什么。如何使用库并向远程系统发出命令的示例

import base64
import paramiko
key = paramiko.RSAKey(data=base64.b64decode(b'AAA...'))
client = paramiko.SSHClient()
client.get_host_keys().add('ssh.example.com', 'ssh-rsa', key)
client.connect('ssh.example.com', username='THE_USER', password='THE_PASSWORD')
stdin, stdout, stderr = client.exec_command('which solsql')
for line in stdout:
    print('... ' + line.strip('\n'))
client.close()

首先,您需要调试错误

使用如下代码:

command = "ssh root@IP which solsql"

try:
    retult = subprocess.check_output(command,shell=True,stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
    raise RuntimeError("command '{}' return with error (code {}): {}".format(e.cmd, e.returncode, e.output))

print ("Result:", result)

它将向您输出错误消息,您将知道该怎么做,例如,ssh可能要求输入密码,或者找不到您的密钥,或者其他什么。

通过ssh运行命令时,shell执行的启动文件集与您以交互方式连接到服务器时不同。因此,根本问题是,当您通过脚本通过
ssh
连接时,安装此工具的路径不在
路径中

一个常见但粗糙的解决方法是强制shell读取带有所需定义的
路径的文件;但当然,这基本上要求您至少知道正确的
路径设置在哪里,因此您最好首先确定该工具的确切安装位置

ssh server '. .bashrc; type -all solsql'
(假设
路径
是在
.bashrc
中设置的;暂时忽略作为您自己和作为
root
执行东西之间的区别。
.bashrc
前面的点和空格非常重要。还要注意我们如何使用POSIX命令
type
,而不是脆性
command,几十年前,它本应自然死亡,但却是可怕的死亡)

如果您对该工具的安装位置有一个很好的想法,那么可以改为这样做

subprocess.check_output(['ssh', 'root@' + ip, '''
    for path in /opt/solidDB/*/bin /usr/local/bin /usr/bin; do
         test -x "$path/solsql" || continue
         echo "$path"
         exit 0
     done
     exit 1'''])

请注意,我们还如何避免(这里是无用的)
shell=True
。可能还会看到您得到了什么错误?路径中添加了
/opt/solidDB/solidDB-6.5/bin
?可能在
中。bash_profile
(源于登录shell),而不是在
中。bashrc
,源于非登录shell(例如,如果您使用命令启动ssh,则启动该命令)。@MihanEntalpo错误为:
subprocess.CalledProcessError:command'sshroot@10.65.163.24“哪个solsql”“返回非零退出状态1
Hey Ortal,如果我的答案有帮助且有效,我可以接受答案,以便其他人可以看到答案是正确的做法。@JackHerer这些答案帮助我理解了问题的原因,因此我选择了另一种方式,您的解决方案似乎很有用,但我没有尝试,我希望得到更简单的解决方案CA修改异常以便可以重新验证它似乎毫无意义。真正的问题是如何避免错误,即找出命令的实际安装位置。我试图帮助提问者检测问题的原因。通过这个新的异常,他可以看到命令的输出,这是他以前没有看到过的,因为没有那么详细的异常消息(命令'sshroot@10.65.163.24“哪个solsql”返回非零退出状态1)。最好找到解决此类问题的方法:以正确的方式进行调试,而不是给出一次性的解决方案,然后等待新问题出现。显示的正是这些信息;您只是在重新表述它。回溯并没有准确显示这些信息。如果您仔细看,您会发现,在我的示例中,e.output被添加到o异常文本体,默认情况下不会在回溯中输出。请自己尝试。只需调用subprocess.check_output(“ssh”)noone@nowhere,shell=True,stderr=subprocess.STDOUT),并告诉我,除了“返回的非零退出状态”之外,该命令还有什么问题但在我的示例中,例外情况是:命令'sshnoone@nowhere“返回时出错(代码255):b”由于stdin不是终端,将不会分配伪终端。\r\nssh:无法解析主机名:名称或服务未知\r\n。请参阅“无法解析主机名…”。当“返回非零退出状态”时,信息更丰富我知道shell=True的意思,我不喜欢它是false,因为语法变得更复杂,更容易出错。事实上,可以说恰恰相反。引用的级别越高,意味着你必须在头脑中展开或猜测更多的内容。总之,
ssh实际上是传递给一个(远程)shell,您只是没有让Python运行一个shell来将字符串传递给远程主机上由
ssh
运行的shell;因此语法便利性的论点是没有意义的,如果不是完全错误的话。(可能还是读一下链接的问题吧;我的答案在这里有点扩展。)