python中farbic和paramiko模块

本文介绍了Python的Fabric库和Paramiko模块,它们分别用于简化SSH连接和执行远程命令。通过示例展示了如何使用Fabric进行任务定义、执行本地和远程命令、上传下载文件,以及通过Paramiko进行文件传输和多服务器的批量操作。这两个工具在自动化运维和部署场景中非常实用。
摘要由CSDN通过智能技术生成

fabric

        Fabric是一个python的远程执行shell的库,同时它也是一个命令行工具。它提供了丰富的同 SSH 交互的接口,可以用来在本地或远程机器上自动化、流水化地执行 Shell 命令。

#python3 安装时使用的是fabric3 :( 安装fabric3之前,需要先卸载fabric.)
# fabric3 支持 python3

pip uninstall fabric
pip3 install fabric3

fabric 不只是一个Python 模块,fabric 还是一个命令行工具,可以使用fab -h查看帮助信息 

E:\my_data\hk-project>fab -V
Fabric3 1.14.post1
Paramiko 2.9.2
E:\my_data\hk-project>fab -h 

入门使用

fabric常用参数
 

-l:显示定义好的任务函数名
-f:指定fab人口文件,默认人口文件名为fabfile.py
-H:指定目标主机,多台主机用“,”号分割

fab -H localhost -f host_type.py function

fabric常用API

local:执行本地命令,如:local('uname -s')
lcd:切换本地目录,如:lcd('/home')
cd:切换远程目录,如:cd('/etc')
run:执行远程命令,如:run('free -m')
sudo:sudo方式执行远程命令,如:sudo('touch /abc')
put:上传本地文件到远程主机,如:put('/hello', '/home/itcast/hello')
get:从远程主机下载文件到本地,如:get('/home/python/world', '/home/itcase/world')
reboot:重启远程主机,如:reboot()
@task:函数装饰器,标识的函数为fab可调用的,非标记的对fab不可见,纯业务逻辑
@runs_once:函数装饰器,标识的函数只会执行一次,不受多台主机影响

fabric全局属性设定

env.host:定义目标主机,如:env.host=['192.168.17.192','192.168.17.193']
env.user:定义用户名,如:env.user="root"
env.port:定义目标主机端口,默认为22,如:env.port=“22”
env.password:定义密码,如:env.password="chuanzhi"
env.passwords:不同的主机不同的密码,如:
    env.passowrds={    
        'root@192.168.117.92:22':'passwd',
        'admin@192.168.117.93:22':'password'
    }

示例1:动态获取远程目录列表

$ cat simple2.py
#!/usr/bin/env python
from fabric.api import *
env.user = 'root'
env.hosts = ['192.168.0.121']
env.password = '1234567'

def remote_task():
    #"with"的作用是让后面的语句继承当前状态,实现"cd /root/ && ls -l'的效果
    with cd('/root'):
        run('ls -l')

===========================================================================
$ fab -f simple2.py remote_task
[192.168.0.121] Executing task 'remote_task'
[192.168.0.121] run: ls -l
[192.168.0.121] out: total 4
[192.168.0.121] out: -rw-------. 1 root root 1273 May 29 11:47 anaconda-ks.cfg
[192.168.0.121] out:


Done.
Disconnecting from 192.168.0.121... done.

示例2:部署LNMP业务服务环境

#!/usr/bin/env python
from fabric.colors import *
from fabric.api import *

env.user = 'root'

env.roledefs = {
    'webservers':['192.168.56.11','192.168.56.12'],
    'dbservers':['192.168.56.13']
}

env.passwords = {
    'root@192.168.56.11:22':'1234567',
    'root@192.168.56.12:22':'1234567',
    'root@192.168.56.13:22':'1234567',
}

@roles('webservers')   #使用webtask任务函数引用'webservers'角色修复符
def webtask():
    print(yellow('Install nginx php php-fpm...'))
    with settings(warn_only=True):
        run("yum -y install nginx")
        run("yum -y install php-fpm php-mysql php-mbstring php-xml php-mcrypt php-gd")
        run("chkconfig --levels 235 php-fpm on")
        run("chkconfig --levels 235 nginx on")


@roles('dbservers')  #dbtask任务函数引用'dbservers'角色修复符
def dbtask():
    print(yellow("Install Mysql..."))
    with settings(warn_only=True):
        run("yum -y install mysql mysql-server")
        run("chkconfig --levels 235 mysqld on")


@roles('webservers','dbservers') #publictask任务函数同时引用两个角色修复符
def publictask():    #部署公共类环境,如epel、ntp等
    print(yellow("Install epel ntp...."))
    with settings(warn_only=True):
        run("wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo")
        run("yum -y install ntp")

def deploy():
    execute(publictask)
    execute(webtask)
    execute(dbtask)


==================================================================================
$ fab -Pf simple6.py deploy
[192.168.56.11] Executing task 'publictask'
[192.168.56.12] Executing task 'publictask'
[192.168.56.13] Executing task 'publictask'Install epel ntp....
[192.168.56.13] run: wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repoInstall epel ntp....
[192.168.56.12] run: wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repoInstall epel ntp....
[192.168.56.11] run: wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
[192.168.56.12] out: --2021-06-23 20:32:30--  http://mirrors.aliyun.com/repo/epel-7.repo
[192.168.56.11] out: --2021-06-23 20:32:30--  http://mirrors.aliyun.com/repo/epel-7.repo
[192.168.56.13] out: --2021-06-23 20:32:30--  http://mirrors.aliyun.com/repo/epel-7.repo....
[192.168.56.13] run: yum -y install ntp
[192.168.56.12] run: yum -y install ntp
[192.168.56.11] run: yum -y install ntp
....
....
....
[192.168.56.11] Executing task 'webtask'
[192.168.56.12] Executing task 'webtask'Install nginx php php-fpm...
[192.168.56.11] run: yum -y install nginx
Install nginx php php-fpm...
[192.168.56.12] run: yum -y install nginx
....
....
....
[192.168.56.13] Executing task 'dbtask'Install Mysql...
[192.168.56.13] run: rpm -ivh http://dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm.....
.....
.....
[192.168.56.13] run: chkconfig --levels 235 mysqld on

paramiko

1)实现了ssh协议

2)实现ssh远程控制

3)实现sftp功能

import paramiko  #安装后导入模块

#创建实例 
ssh = paramiko.SSHClient()  
#相当于在询问是否接受服务器秘钥时自动回答yes
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())  

ssh.connect('192.168.59.112',username='root',password='211314')

"""
stdin.标准输入       用于实现交互式命令
stdout.标准输出       保存命令的正确执行结果
stderr.标准错误输出   保存命令的错误信息
"""

stdin ,stdout ,stderr = ssh.exec_command('mkdir /root/newdir')
print(str(stdout.read()))
ssh.close

案例代码,查看多台服务器的磁盘使用率(此代码演示查看192.168.59.131-132)

import paramiko
import sys

def sshExecCMD(ip , uesrname , password ):
    ssh_client = paramiko.SSHClient()
    ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy)
    print("请求%s:" % ip)
    try:
       ssh_client.connect(hostname=ip ,username=uesrname ,password=password)
    except Exception as e:
        print("服务器%s连接失败!!!" % ip)
        print(e)
        sys.exit()

    stdin ,stdout ,stderr = ssh_client.exec_command("df -h")
    print(stdout.read().decode("utf-8"))

    ssh_client.close()

if __name__ == '__main__':
    for i in range(131, 133):
        server = {
            '192.168.59.' + str(i): {
                "username": "root",
                "password": "211314",
                #"port": 22
            }
        }
        for ip, info in server.items():
            sshExecCMD(
                ip=ip,
                uesrname=info.get("username"),
                password=info.get("password"),
                #port=info.get("port")
            )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
/usr/bin/python3.7 /root/PycharmProjects/pythonProject/webone.py
请求192.168.59.131:
文件系统                 容量  已用  可用 已用% 挂载点
devtmpfs                 1.9G     0  1.9G    0% /dev
tmpfs                    1.9G     0  1.9G    0% /dev/shm
tmpfs                    1.9G   12M  1.9G    1% /run
tmpfs                    1.9G     0  1.9G    0% /sys/fs/cgroup
/dev/mapper/centos-root  4.4G  3.7G  744M   84% /
/dev/sda1               1014M  151M  864M   15% /boot
tmpfs                    1.9G   12K  1.9G    1% /var/lib/kubelet/pods/33185cf6-cdfe-4e1e-9a31-e8de94263fa3/volumes/kubernetes.io~secret/flannel-token-xkp6d
tmpfs                    1.9G   12K  1.9G    1% /var/lib/kubelet/pods/846866a4-0983-4977-946b-0d91e5576b90/volumes/kubernetes.io~secret/kube-proxy-token-nxmps
overlay                  4.4G  3.7G  744M   84% /var/lib/docker/overlay2/c585e004fd183248031ba2bd41ceaeca30aba69e4c29842c61c5b33caace5827/merged
shm                       64M     0   64M    0% /var/lib/docker/containers/2bf609ddce0c66f1313210b63aa03997ac073b56466a3426504b2ce6005c0193/mounts/shm
overlay                  4.4G  3.7G  744M   84% /var/lib/docker/overlay2/0e1cf81dbe957116a576033c11cb2d470517eac9daf8071488a43826e7740d7c/merged
overlay                  4.4G  3.7G  744M   84% /var/lib/docker/overlay2/6cff54918ae7b8ba0f9acc38ae2481aa9602039a4471c01f651a301df163a01a/merged
shm                       64M     0   64M    0% /var/lib/docker/containers/94f5576393ba10fc9e7515d5c70722e3738ebed8ebf1a4d98bcde259f15ff50a/mounts/shm
overlay                  4.4G  3.7G  744M   84% /var/lib/docker/overlay2/c709ceeb38a5fe3f310466607d79d74f6cde1bf0089384f214a7322d3d366207/merged
tmpfs                    378M     0  378M    0% /run/user/0

请求192.168.59.132:
服务器192.168.59.132连接失败!!!
[Errno None] Unable to connect to port 22 on 192.168.59.132

进程已结束,退出代码为 0

paramiko上传下载文件

#coding:utf-8

import paramiko

def sshFile():
    #与服务器创建ssh连接
    ssh_conn = paramiko.Transport(("192.168.59.128", 22))
    ssh_conn.connect(username="root", password="211314")
    #基于ssh连接创建ftp客户端
    ftp_client = paramiko.SFTPClient.from_transport(ssh_conn)

    #下载文件  上传和下载要保证客户端和服务端的文件名一致  ./.*?/name == .\.*?\name
    ftp_client.get('/etc/hosts',r'E:\learndj\hosts')
    #上传文件
    #ftp_client.put(r"E:\learndj\hosts","/mnt/hosts")

    ssh_conn.close()

if __name__ == '__main__':
    sshFile()

paramiko往多个服务器上传案例

# coding:utf-8
import paramiko
import os

# localfile:本地文件夹名
# remotedir:服务器目录名称
def sshPutFile(ip, port, username, password, localfile, remotedir):
    # 创建ssh链接
    ssh_conn = paramiko.Transport((ip, port))
    ssh_conn.connect(username=username, password=password)

    # 获取源文件的文件名
    file_name = os.path.basename(localfile)

    # 处理服务器目录名称 /etc/
    if not remotedir.endswith("/"):
        remotedir = remotedir + "/"
    system_file = remotedir + file_name

    ftp_client = paramiko.SFTPClient.from_transport(ssh_conn)
    ftp_client.put(localfile, system_file)

    ssh_conn.close()


if __name__ == '__main__':
    servers = {
        "192.168.59.128":{
            "username": "root",
            "password": "211314",
            "port": 22
        },
        "192.168.59.130": {
            "username": "root",
            "password": "211314",
            "port": 22
        },
        "192.168.59.131": {
            "username": "root",
            "password": "211314",
            "port": 22
        }
    }

    source_file = input("源文件名称(绝对路径):")
    server_dir = input("服务器目录路径:")

    for ip,info in servers.items():
        sshPutFile(
            ip= ip,
            port= info.get("port"),
            username= info.get("username"),
            password= info.get("password"),
            localfile = source_file,
            remotedir= server_dir,
        )

        查看是否上传成功,根据需求写获取ip的方式,此方式仅供参考,配置数量较大是可以采用多线程的方式增加效率。

import paramiko

ips_info = [
    #("ip","username","password")
    ("101.43.129.109","root","Zgy666.."),
    ("10.1.128.14","root","rootroot"),
]

cmds = """
ls
free -h 
df -h
"""

class ssh_Client:
    def __init__(self):
        self.cmd = cmds
        for ip_info in ips_info:
            self.ip = ip_info[0]
            self.username = ip_info[1]
            self.passwd = ip_info[2]

            print("请求%s:" % self.ip)
            try:
                ssh = paramiko.SSHClient()
                ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy)
                ssh.connect(hostname=self.ip, username=self.username, password=self.passwd)
                stdin, stdout, stderr = ssh.exec_command(self.cmd)
                print(stdout.read().decode("utf-8"))
            except Exception as e:
                print(self.ip, "连接失败,", e)
            ssh.close()


if __name__ == '__main__':
    ssh_Client()

# coding:utf-8
import os
import sys
from concurrent.futures import ThreadPoolExecutor
import paramiko
from pathlib import Path

self_name = sys.argv[0].rsplit('/', 1)[1]
self_dir = os.listdir()
self_dir.remove(self_name)

localhost = {
    # "192.168.0.50":("root","rootroot"),
    "101.43.129.109": ("root", "Zgy666.."),
    # "10.1.128.13": ("root", "rootroot"),
}

BASE_DIR = Path(__file__).resolve().parent
# 服务端接收文件路径
server_path = "/mnt/"


def printTotals(transferred, toBeTransferred):
    print("\r", end="")
    # print("Download progress: {}%: ".format(transferred*100//toBeTransferred), "▋" * (transferred*50 // toBeTransferred), end="")
    print(f"进度:{'▋' * (transferred * 50 // toBeTransferred)} {transferred * 100 // toBeTransferred}% ", end="")
    sys.stdout.flush()
    # print("Transferred: {0}\tOut of: {1}".format(transferred, toBeTransferred) )


def sshFile(localhost, username, password, put_path, load_path):
    try:
        # 与服务器创建ssh连接
        ssh_conn = paramiko.Transport((localhost, 22))
        ssh_conn.connect(username=username, password=password)
        # 基于ssh连接创建ftp客户端
        ftp_client = paramiko.SFTPClient.from_transport(ssh_conn)
        # 上传文件
        local_nowfile = put_path.split("/")[-1]
        print("\n%s =====> %s \n" % (localhost, local_nowfile), end="")
        ftp_client.put(put_path, load_path, callback=printTotals)
        print("\n%s %s 传输完成!\n" % (localhost, local_nowfile), end="")
        ssh_conn.close()
    except Exception as e:
        print(localhost,e)

def put_File(hostname, username, password):
    for path_file in self_dir:
        user_path_file = os.path.join(BASE_DIR, path_file)
        server_path_file = os.path.join(server_path, path_file)
        sshFile(hostname, username, password, user_path_file, server_path_file)

def pool_run():
    pool = ThreadPoolExecutor(10)
    for host, user_info in localhost.items():
        try:
            pool.submit(put_File, host, user_info[0], user_info[1])

        except Exception as e:
            print(host, e)

def run():
    for host, user_info in localhost.items():
        put_File(host,user_info[0],user_info[1])


if __name__ == '__main__':
    run()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值