【问题标题】:ssh using sshpass in python seems to not work在 python 中使用 sshpass 的 ssh 似乎不起作用
【发布时间】:2013-09-24 22:31:45
【问题描述】:

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

我的 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()

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

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

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

【问题讨论】:

  • 尝试使用 paramiko ssh 并执行命令。
  • 当我们执行“pxssh.pxssh.login('hostname', ''username', 'password')”时。有没有办法同时 ssh 到 5 个系统。可能我需要创建一个提升名称、用户名和密码的列表并遍历它们。如果您有任何好主意,将不胜感激。
  • pxssh 或 pexpect 目前适用于 1 个系统。只需要与多个 ssh 客户端一起使用即可。使用以前的方法,我不认为它是 ssh'ing 到指定的 IP,因为我更改了路径名并看到它正在转到主机中指定的位置,而不是在客户端上。
  • 当它打印 /home/ 你在 /home/@localhost 而不是 /home/@192.168.1.97

标签: python linux bash shell ssh


【解决方案1】:

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

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

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

【讨论】:

  • 对不起,我错过了输出中的那部分。它确实在 os.getcwd() 上打印 /home ,但我不确定 ssh 是否成功。尽管 print 确实被执行了,但这意味着 sshpass 进入没有任何问题。在检查进程“ps -ef | grep sshpass”时,我没有看到任何“sshpass”会话,这让我认为某处存在隐藏问题。
  • 当您调用在本地机器上执行的sh my_script 时...您需要使用 ssh 库(如 paramiko ssh)
  • 但是它不会成功连接到客户端使用 sshpass 并在客户端上执行 "sh myscript.sh"。?
  • @learning 它将在客户端而不是远程服务器上运行 myscript.sh。即使使用run2 生成的进程也在客户端上运行,即使它正在与远程服务器交互。
【解决方案2】:

您的“主”目录通常类似于/home/<username>/users/<username>。一般来说,shell 通常会接受 ~ 作为主目录路径的同义词。这是否可行:

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

【讨论】:

  • 他的问题是他在本地系统上调用sh myscript ...它不存在
【解决方案3】:

这是一个使用 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()

【讨论】:

    【解决方案4】:

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

    我的建议是制作完整的 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()
    

    【讨论】:

    • 请注意下面修改代码中的注释,以便更好地理解 print "I am in 192.168.1.97" # 这里你假设你在远程机器上,但实际上你只在本地机器上跨度>
    猜你喜欢
    • 2019-01-19
    • 2017-08-31
    • 1970-01-01
    • 2011-08-18
    • 2017-12-31
    • 2020-11-18
    • 1970-01-01
    • 2018-08-11
    • 1970-01-01
    相关资源
    最近更新 更多