bash 在 python 中使用 sshpass 的 ssh 似乎不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18901470/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 06:37:55  来源:igfitidea点击:

ssh using sshpass in python seems to not work

pythonlinuxbashshellssh

提问by Quick Silver

I have a python script which is supposed to ssh in to a client and execute a bash from the client. As a test scenario I am using just 1 machine to connect but the objective is to connect to several clients and execute bash scripts from those machines.

我有一个 python 脚本,它应该通过 ssh 连接到客户端并从客户端执行 bash。作为测试场景,我只使用一台机器进行连接,但目标是连接到多个客户端并从这些机器执行 bash 脚本。

My Python code:

我的 Python 代码:

 import os 
 import subprocess
 import time


def ssh_login_execute():
    if device['PWD'] != "":
            run=('sshpass -p %s ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -t -p %s %s@%s' % (device['PWD'], device['PORT'], device['USER'], device['IP']))
    else:
            run=('ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -t -p %s %s@%s' % (device['PORT'], device['USER'], device['IP']))

    cmd = ('cd %s' % (script_path))

    run2=run.split()
    run2.append(cmd)
    t=subprocess.Popen(run2, stdout=subprocess.PIPE, stderr=open(os.devnull, 'w'))
    print "I am in 192.168.1.97"
    execute_tg()
    return t

def execute_tg():
   path = "/home/"
   os.chdir(path)
   print os.getcwd()
   cmd=("sh my_script.sh")
   t=subprocess.Popen(cmd.split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

if __name__ == "__main__":
    device = {}
    device['PORT']=22
    device['PWD']= "abcd"
    device['USER']= "root"
    device['IP']= "192.168.1.97"
    script_path= "/home/"
    ssh_login_execute()

On running the code "python script.py", I see output as:

在运行代码“python script.py”时,我看到输出为:

  I am in 192.168.1.97
  /home/
  Output is sh: 0: Can't open my_script.sh

Although the "my_script.sh" is in /home directory in 192.168.1.97. How do I get rid of this issue and at the same time make it scalable to ssh to multiple clients and execute bash.

尽管“my_script.sh”位于 192.168.1.97 的 /home 目录中。我如何摆脱这个问题,同时使其可扩展到 ssh 到多个客户端并执行 bash。

回答by konsolebox

Your script my_script.shis probably not in /home/as expected in the code.

您的脚本my_script.sh可能/home/与代码中的预期不符。

   path = "/home/"
   os.chdir(path)
   print os.getcwd()
   cmd=("sh my_script.sh")

Also it should print the current directory as well with print os.getcwd(). You should change those values based on the real location of your script.

它还应该打印当前目录以及print os.getcwd(). 您应该根据脚本的实际位置更改这些值。

回答by Jay

Here is an example utilizing the paramiko module and using the getpass module:

这是一个使用 paramiko 模块并使用 getpass 模块的示例:

#!/usr/bin/python
import paramiko
import getpass
class Remote():
    def __init__(self, hostfile, username, commands):
        self.hostfile = hostfile
        self.username = username
        self.commands = commands
    def execute(self):
        client = paramiko.SSHClient()
        client.load_system_host_keys()
        ##########################################################
        # just in case it does not recognize the known_host keys
        # in the known_hosts file
        ##########################################################
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        self.password = getpass.getpass("Password: ")
        for i in self.hostfile.readlines():
            print("Connecting to..." + i)
            client.connect(i.strip(), 22, self.username, self.password)
            stdin, stdout, stderr = client.exec_command(self.commands)
            for t in stdout.readlines():
                print(t.strip())
            for t in stderr.readlines():
                print(t.strip())
#--------------------------------------------------------
commands="""
echo "##################################################";
hostname;
echo "##################################################";
uname -a;
echo "##################################################";
dmidecode -t bios
"""
#---------------------------------------------------------
username = raw_input("Username: ")
hostfile = open('hosts')
a = Remote(hostfile, username, commands)
a.execute()

回答by Tejas

Actually sshpass executes ssh command/connection in a single go. Once the remote query is executed through subprocess.Popen() your program control will be back to local machine in the next line. And your program will give error "Can't open my_script.sh" because your script is not on local machine whereas it is on remote machine.

实际上 sshpass 一次性执行 ssh 命令/连接。通过 subprocess.Popen() 执行远程查询后,您的程序控制权将在下一行返回到本地计算机。并且您的程序将给出错误“无法打开 my_script.sh”,因为您的脚本不在本地机器上,而在远程机器上。

My suggestion is to make the full sshpass command with what to execute in a single program varibale (in your case 'run2' variable) and pass it to subprocess.Popen() in single go. Modified code is as below:

我的建议是使完整的 sshpass 命令包含在单个程序变量(在您的情况下为“run2”变量)中执行的内容,并将其一次性传递给 subprocess.Popen()。修改后的代码如下:

import os 
import subprocess
import time

def ssh_login_execute():
    if device['PWD'] != "":
        run=('sshpass -p %s ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -t -p %s %s@%s' % (device['PWD'], device['PORT'], device['USER'], device['IP']))
    else:
        run=('ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -t -p %s %s@%s' % (device['PORT'], device['USER'], device['IP']))

    cmd = ('sh /%s/%s' % (script_path,'my_script.sh'))

    run2=run.split()
    run2.append(cmd)
    t=subprocess.Popen(run2, stdout=subprocess.PIPE, stderr=open(os.devnull, 'w'))
    print "I am in 192.168.1.97" # HERE YOU ASSUMED THAT YOU ARE IN REMOTE MACHINE BUT ACTUALLY YOU ARE IN LOCAL MACHINE ONLY
    return t

if __name__ == "__main__":
    device = {}
    device['PORT']=22
    device['PWD']= "abcd"
    device['USER']= "root"
    device['IP']= "192.168.1.97"
    script_path= "/home/"
    ssh_login_execute()

回答by Digital Trauma

Your "home" directory is usually something like /home/<username>or perhaps /users/<username>. In general shells will generally accept ~as a synonym for the path to your home directory. Does this work instead:

你的“家”目录通常是这样/home/<username>或可能/users/<username>。通常,shell 通常会接受~作为主目录路径的同义词。这是否有效:

cmd=("sh ~/my_script.sh")