Python paramiko tool connects to Linux and executes commands

conf.xml

VM:
  ip:
    192.168.75.130
  port:
    22
  root_name:
    root
  root_password:
    hjfhjf0501
  name:
    smis
  password:
    Og123456

parseyml.py

def read_yaml_k(conf_path, k):
    # 打开文件
    with open(conf_path, "r", encoding="utf-8") as f:
        data = yaml.load(f, Loader=yaml.FullLoader)
        try:
            # 判断传入的n是否在存在
            if k in data.keys():
                return data[k]
            else:
                print(f"n:{
      
      k}不存在")
        except Exception as e:
            print(f"key值{
      
      e}不存在")

LinuxConnector.py

import logging
import stat
from stat import S_ISDIR
import paramiko
import os
import time
from src.tool.parseyml import read_yaml_k


def get_all_files_in_local_dir(local_dir):
    """递归获取当前目录下所有文件目录"""
    all_files = []
    # 获取当前指定目录下的所有目录及文件,包含属性值
    files = os.listdir(local_dir)
    for x in files:
        # local_dir目录中每一个文件或目录的完整路径
        filename = os.path.join(local_dir, x)
        # 如果是目录,则递归处理该目录
        if os.path.isdir(filename):
            all_files.extend(get_all_files_in_local_dir(filename))
        else:
            all_files.append(filename)
    return all_files

class LinuxConnector:

    def __init__(self, path):
        vmConfig = read_yaml_k(path, 'VM')
        self.ip = vmConfig['ip']
        self.port = vmConfig['port']
        self.root_name = vmConfig['root_name']
        self.root_passwd = vmConfig['root_password']
        self.u_name = vmConfig['name']
        self.u_passwd = vmConfig['password']
        self.result = []

        self.ssh = paramiko.SSHClient()
        self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

        self.ssh.connect(hostname=self.ip, port=self.port,
                         username=self.root_name, password=self.root_passwd,
                         allow_agent=False, look_for_keys=False)

        self.tranport = paramiko.Transport((self.ip, self.port))

        self.tranport.connect(username=self.root_name, password=self.root_passwd)
        self.sftp = paramiko.SFTPClient.from_transport(self.tranport)

    def getssh(self):
        return self.ssh

    def close_ssh(self):
        self.ssh.close()
        self.sftp.close()

    def execCommand(self, command):
        stdin, stdout, stderr = self.ssh.exec_command(command)
        return stdin, stdout, stderr

    # 执行多条命令,注意传入的参数有个list
    def execMultiCmd(self, cmds: list) -> (str, str):
        cmd = ";".join(cmds)
        _, stdout, stderr = self.ssh.exec_command(cmd, get_pty=True)
        result = stdout.read().decode('utf-8')
        err = stderr.read().decode('utf-8')
        return result, err

	"""
    :param localfile_path:待上传文件路径
    :param remote_path:远程路径
    :return:
    """
    def UploadFile_path(self, remote_path, localfile_path):
        # 待上传目录名
        local_pathname = os.path.split(localfile_path)[-1]
        # 上传远程后的目录名
        real_remote_Path = remote_path + local_pathname

        # 判断是否存在,不存在则创建
        try:
            self.sftp.stat(remote_path)
        except Exception as e:
            self.ssh.exec_command("mkdir -p %s" % remote_path)

        self.ssh.exec_command("mkdir -p %s" % real_remote_Path)

        toremote_path = remote_path + local_pathname

        self.sftp.put(localfile_path, toremote_path)
        print(localfile_path, toremote_path)

    """
    :param local_path:待上传文件夹路径
    :param remote_path:远程路径
    :return:
    """
    def UploadDir_path(self, remote_path, local_path):
        # 待上传目录名
        local_pathname = os.path.split(local_path)[-1]
        # 上传远程后的目录名
        real_remote_Path = remote_path + local_pathname

        # 判断是否存在,不存在则创建
        try:
            self.sftp.stat(remote_path)
        except Exception as e:
            self.ssh.exec_command("mkdir -p %s" % remote_path)

        self.ssh.exec_command("mkdir -p %s" % real_remote_Path)
        # 获取本地文件夹下所有文件路径
        all_files = get_all_files_in_local_dir(local_path)
        # 依次判断远程路径是否存在,不存在则创建,然后上传文件
        for file_path in all_files:
            # 统一win和linux 路径分隔符
            file_path = file_path.replace("\\", "/")
            # 用本地根文件夹名分隔本地文件路径,取得相对的文件路径
            off_path_name = file_path.split(local_pathname)[-1]
            # 取得本地存在的嵌套文件夹层级
            abs_path = os.path.split(off_path_name)[0]
            # 生产期望的远程文件夹路径
            reward_remote_path = real_remote_Path + abs_path
            # 判断期望的远程目录是否存在,不存在则创建
            try:
                self.sftp.stat(reward_remote_path)
            except Exception as e:
                self.ssh.exec_command("mkdir -p %s" % reward_remote_path)
            # 待上传的文件名
            abs_file = os.path.split(file_path)[1]
            # 上传后的远端路径,文件名不变
            to_remote = reward_remote_path + '/' + abs_file
            time.sleep(0.1)
            self.sftp.put(file_path, to_remote)
            print(file_path, to_remote)
	
	"""
    :param local_path:文件夹下载后存储的路径
    :param remote_path:远程文件夹存储的路径
    :return:
    """
    def DownloadDir_path(self, remote_path, local_path):
        if os.path.isdir(local_path):
            pass
        else:
            os.makedirs(local_path)

        # check file/dir
        isfile_list = []
        isdir_list = []
        remote_allfiles = self.sftp.listdir_attr(remote_path)

        for f in remote_allfiles:
            remote_file = remote_path + "/" + f.filename
            dirname = remote_path.split("/")[-1]
            local_file = local_path + "/" + dirname + "/" + f.filename
            if stat.S_ISDIR(f.st_mode):
                isdir_list.append(remote_file)
            else:
                isfile_list.append(remote_file)

        print(isdir_list)
        print(isfile_list)

        # first step: get file
        for file_name in isfile_list:
            remote_file = file_name
            try:
                os.makedirs(os.path.join(local_path, file_name.split("/")[-2]))
            except:
                pass

            local_file = local_path + "/" + file_name.split("/")[-2] + "/" + file_name.split("/")[-1]
            self.sftp.get(remote_file, local_file)

        # second step: loop dir
        n = 0

        for dir_name in isdir_list:
            if n > 0:
                local_path = local_path
            else:
                local_path = local_path + "/" + dir_name.split("/")[-2]
            remote_path = dir_name
            self.DownloadDir_path(remote_path, local_path)
            n += 1

        return self.result

Guess you like

Origin blog.csdn.net/twi_twi/article/details/129972466