Python自动化运维03

本文主要介绍Python自动化运维的常用模块,比如:paramiko、Fabric等。

1. paramiko模块

  • 基于用户名和密码的 sshclient 方式登录

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #!/usr/bin/env python
    # coding:utf-8

    import paramiko

    host='123.20.62.15'
    port=22
    username='root'
    password='your pass'

    if __name__ == '__main__':
    paramiko.util.log_to_file('paramiko.log')
    ssh=paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect(host,port,username,password)
    stdin,stdout,stderr=ssh.exec_command('ifconfig')
    print stdout.read()
    ssh.close()
  • 基于用户名和密码的 transport 方式登录
    示例1:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #!/usr/bin/env python
    # coding:utf-8

    import paramiko

    host='123.20.62.15'
    port=22
    username='root'
    password='your pass'

    if __name__ == '__main__':
    trans=paramiko.Transport(host,port)
    trans.connect(username=username,password=password)

    ssh=paramiko.SSHClient()
    ssh._transport=trans
    stdin, stdout, stderr = ssh.exec_command('df -hl')
    print(stdout.read().decode())
    trans.close()

示例2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/env python
# coding:utf-8

import paramiko
import os

host='123.20.62.15'
port=22
username='root'
password='your pass'
dir_path='/root/'

if __name__ == '__main__':
trans=paramiko.Transport(host,port)
trans.connect(username=username,password=password)

sftp=paramiko.SFTPClient.from_transport(trans)
files=sftp.listdir(dir_path)

for f in files:
print f
sftp.get(os.path.join(dir_path,f),f)

trans.close()

  • 基于公钥密钥的 SSHClient 方式登录

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #!/usr/bin/env python
    # coding:utf-8

    import paramiko


    # 指定本地的RSA私钥文件,如果建立密钥对时设置的有密码,password为设定的密码,如无不用指定password参数
    pkey = paramiko.RSAKey.from_private_key_file('/home/super/.ssh/id_rsa', password='12345')
    # 建立连接
    ssh = paramiko.SSHClient()
    ssh.connect(hostname='192.168.2.129',
    port=22,
    username='super',
    pkey=pkey)
    # 执行命令
    stdin, stdout, stderr = ssh.exec_command('df -hl')
    # 结果放到stdout中,如果有错误将放到stderr中
    print(stdout.read().decode())
    # 关闭连接
    ssh.close()
  • 基于密钥的 Transport 方式登录

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    #!/usr/bin/env python
    # coding:utf-8

    import paramiko

    # 指定本地的RSA私钥文件,如果建立密钥对时设置的有密码,password为设定的密码,如无不用指定password参数
    pkey = paramiko.RSAKey.from_private_key_file('/home/super/.ssh/id_rsa', password='12345')
    # 建立连接
    trans = paramiko.Transport(('192.168.2.129', 22))
    trans.connect(username='super', pkey=pkey)

    # 将sshclient的对象的transport指定为以上的trans
    ssh = paramiko.SSHClient()
    ssh._transport = trans

    # 执行命令,和传统方法一样
    stdin, stdout, stderr = ssh.exec_command('df -hl')
    print(stdout.read().decode())

    # 关闭连接
    trans.close()

    #################### 传文件 SFTP ##################
    #!/usr/bin/env python
    # coding:utf-8

    import paramiko

    # 实例化一个trans对象# 实例化一个transport对象
    trans = paramiko.Transport(('192.168.2.129', 22))
    # 建立连接
    trans.connect(username='super', password='super')

    # 实例化一个 sftp对象,指定连接的通道
    sftp = paramiko.SFTPClient.from_transport(trans)
    # 发送文件
    sftp.put(localpath='/tmp/11.txt', remotepath='/tmp/22.txt')
    # 下载文件
    # sftp.get(remotepath, localpath)
    trans.close()
  • 实现输入命令立马返回结果的功能

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    #!/usr/bin/env python
    # coding:utf-8

    import paramiko
    import os
    import select
    import sys

    # 建立一个socket
    trans = paramiko.Transport(('192.168.2.129', 22))
    # 启动一个客户端
    trans.start_client()

    # 如果使用rsa密钥登录的话
    '''
    default_key_file = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa')
    prikey = paramiko.RSAKey.from_private_key_file(default_key_file)
    trans.auth_publickey(username='super', key=prikey)
    '''
    # 如果使用用户名和密码登录
    trans.auth_password(username='super', password='super')
    # 打开一个通道
    channel = trans.open_session()
    # 获取终端
    channel.get_pty()
    # 激活终端,这样就可以登录到终端了,就和我们用类似于xshell登录系统一样
    channel.invoke_shell()
    # 下面就可以执行你所有的操作,用select实现
    # 对输入终端sys.stdin和 通道进行监控,
    # 当用户在终端输入命令后,将命令交给channel通道,这个时候sys.stdin就发生变化,select就可以感知
    # channel的发送命令、获取结果过程其实就是一个socket的发送和接受信息的过程
    while True:
    readlist, writelist, errlist = select.select([channel, sys.stdin,], [], [])
    # 如果是用户输入命令了,sys.stdin发生变化
    if sys.stdin in readlist:
    # 获取输入的内容
    input_cmd = sys.stdin.read(1)
    # 将命令发送给服务器
    channel.sendall(input_cmd)

    # 服务器返回了结果,channel通道接受到结果,发生变化 select感知到
    if channel in readlist:
    # 获取结果
    result = channel.recv(1024)
    # 断开连接后退出
    if len(result) == 0:
    print("\r\n**** EOF **** \r\n")
    break
    # 输出到屏幕
    sys.stdout.write(result.decode())
    sys.stdout.flush()

    # 关闭通道
    channel.close()
    # 关闭链接
    trans.close()

2. Python运维管理组件Fabric

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from datetime import datetime
from fabric.api import *

# 登录用户和主机名:
env.user = 'root'

env.password='xxxxx'
env.hosts = ['192.168.0.1','192.168.0.2'] # 如果有多个主机,fabric会自动依次部署

def pack():
' 定义一个pack任务 '
# 打一个tar包:
tar_files = ['*.py', 'static/*', 'templates/*', 'favicon.ico']
local('rm -f example.tar.gz')
local('tar -czvf example.tar.gz --exclude=\'*.tar.gz\' --exclude=\'fabfile.py\' %s' % ' '.join(tar_files))

def deploy():
' 定义一个部署任务 '
# 远程服务器的临时文件:
remote_tmp_tar = '/tmp/example.tar.gz'
tag = datetime.now().strftime('%y.%m.%d_%H.%M.%S')
run('rm -f %s' % remote_tmp_tar)
# 上传tar文件至远程服务器:
put('shici.tar.gz', remote_tmp_tar)
# 解压:
remote_dist_dir = '/srv/www.example.com@%s' % tag
remote_dist_link = '/srv/www.example.com'
run('mkdir %s' % remote_dist_dir)
with cd(remote_dist_dir):
run('tar -xzvf %s' % remote_tmp_tar)
# 设定新目录的www-data权限:
run('chown -R www-data:www-data %s' % remote_dist_dir)
# 删除旧的软链接:
run('rm -f %s' % remote_dist_link)
# 创建新的软链接指向新部署的目录:
run('ln -s %s %s' % (remote_dist_dir, remote_dist_link))
run('chown -R www-data:www-data %s' % remote_dist_link)
# 重启服务:
fcgi = '/etc/init.d/py-fastcgi'
with settings(warn_only=True):
run('%s stop' % fcgi)
run('%s start' % fcgi)
---------------- The End ----------------