14.2. paramiko(ssh秘钥执行命令)

  • paramiko模块介绍:

Paramiko是一个Python实施SSHv2的协议,提供客户端和服务器的功能。
虽然它利用一个Python C扩展低级别加密的paramiko本身就是围绕SSH联网概念的纯Python接口。
Paramiko官网:http://www.paramiko.org/

14.2.1. 安装

sudo apt-get install python-setuptools
easy_install
sudo apt-get install python-all-dev
sudo apt-get install build-essential

14.2.2. paramiko实例(账号密码登录执行命令)

#!/usr/bin/python
#ssh
import paramiko
import sys,os

host = '10.152.15.200'
user = 'peterli
password = '123456'

s = paramiko.SSHClient()                                 # 绑定实例
s.load_system_host_keys()                                # 加载本地HOST主机文件
s.set_missing_host_key_policy(paramiko.AutoAddPolicy())  # 允许连接不在know_hosts文件中的主机
s.connect(host,22,user,password,timeout=5)               # 连接远程主机
while True:
        cmd=raw_input('cmd:')
        stdin,stdout,stderr = s.exec_command(cmd)        # 执行命令
        cmd_result = stdout.read(),stderr.read()         # 读取命令结果
        for line in cmd_result:
                print line,
s.close()

14.2.3. 代码示例2:

#!/usr/bin/env python
#-*- coding:utf8 -*-
import paramiko
import time

ip = "172.16.10.10"
port= 22
username="root"
passwd="superadmin"


def ssh2(ip,port,username,passwd,cmd):
    try:
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh.connect(ip,port,username,passwd,timeout=5)
        chan=ssh.invoke_shell()
        print(chan.recv(1024))
        for m in cmd:
            res = chan.sendall(m+"\n")
            time.sleep(float(1))
        print(chan.recv(1024))
        ssh.close()
    except Exception as e:
        print(e)

cmd=['ls']
ssh2(ip,port,username,passwd,cmd)

代码示例2

#!/usr/bin/env python
#-*- coding:utf8 -*-
import paramiko,sys
# 创建SSHClient对象
hostname = "172.16.10.10"
port=22
username="root"
password="superadmin"

#使用公钥登录ssh,进行连接
def ssh_connect_key(host,user,key_file,cmd):
    ssh=paramiko.SSHClient()
    ssh.load_system_host_keys()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    key=paramiko.RSAKey.from_private_key_file(key_file)
    ssh.connect(hostname=host,username=user,pkey=key,timeout=30)
    stdin,stdout,stderr=ssh.exec_command(cmd)
    result=stdout.read().decode()     #python3 bytes格式转换为sting,python2无需decode,result=str(stdout.read(),'utf8)
    ssh.close()
    return result

#使用用户名、密码来登录
def ssh_connect(host,user,password,cmd):
    ssh=paramiko.SSHClient()
    ssh.load_system_host_keys()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect(hostname=host,username=user,password=password,timeout=30)
    stdin,stdout,stderr=ssh.exec_command(cmd)
    result=stdout.read()
    ssh.close()
    return result

if __name__ == '__main__':
    # a=len(sys.argv)
    # if a!=5:
    #     print ("参数个数不对,请输入四个参数!")
    # else:
    #     host=sys.argv[1]
    #     user=sys.argv[2]
    #     password=sys.argv[3]
    #     cmd=sys.argv[4]
    #     try:
    #         out=ssh_connect(host,user,password,cmd)
    #         print (out)
    #     except:
    #         print ("usages:python ssh2.py '192.168.10.129' 'root' '123456' 'ls /root'")

    ssh_connect(hostname,username,password,"df -Th")

14.2.4. paramiko实例(传送文件)

#!/usr/bin/evn python
import os
import paramiko
host='127.0.0.1'
port=22
username = 'peterli'
password = '123456'
ssh=paramiko.Transport((host,port))
privatekeyfile = os.path.expanduser('~/.ssh/id_rsa')
mykey = paramiko.RSAKey.from_private_key_file( os.path.expanduser('~/.ssh/id_rsa'))   # 加载key 不使用key可不加
ssh.connect(username=username,password=password)           # 连接远程主机
# 使用key把 password=password 换成 pkey=mykey
sftp=paramiko.SFTPClient.from_transport(ssh)               # SFTP使用Transport通道
sftp.get('/etc/passwd','pwd1')                             # 下载 两端都要指定文件名
sftp.put('pwd','/tmp/pwd')                                 # 上传
sftp.close()
ssh.close()

14.2.5. paramiko实例(密钥执行命令)

#!/usr/bin/python
#ssh
import paramiko
import sys,os
host = '10.152.15.123'
user = 'peterli'
s = paramiko.SSHClient()
s.load_system_host_keys()
s.set_missing_host_key_policy(paramiko.AutoAddPolicy())
privatekeyfile = os.path.expanduser('~/.ssh/id_rsa')             # 定义key路径
mykey = paramiko.RSAKey.from_private_key_file(privatekeyfile)
# mykey=paramiko.DSSKey.from_private_key_file(privatekeyfile,password='061128')   # DSSKey方式 password是key的密码
s.connect(host,22,user,pkey=mykey,timeout=5)
cmd=raw_input('cmd:')
stdin,stdout,stderr = s.exec_command(cmd)
cmd_result = stdout.read(),stderr.read()
for line in cmd_result:
        print line,
s.close()

14.2.6. ssh并发(Pool控制最大并发)

#!/usr/bin/env python
#encoding:utf8
#ssh_concurrent.py

import multiprocessing
import sys,os,time
import paramiko

def ssh_cmd(host,port,user,passwd,cmd):
    msg = "-----------Result:%s----------" % host

    s = paramiko.SSHClient()
    s.load_system_host_keys()
    s.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    try:
        s.connect(host,22,user,passwd,timeout=5)
        stdin,stdout,stderr = s.exec_command(cmd)

        cmd_result = stdout.read(),stderr.read()
        print msg
        for line in cmd_result:
                print line,

        s.close()
    except paramiko.AuthenticationException:
        print msg
        print 'AuthenticationException Failed'
    except paramiko.BadHostKeyException:
        print msg
        print "Bad host key"

result = []
p = multiprocessing.Pool(processes=20)
cmd=raw_input('CMD:')
f=open('serverlist.conf')
list = f.readlines()
f.close()
for IP in list:
    print IP
    host=IP.split()[0]
    port=int(IP.split()[1])
    user=IP.split()[2]
    passwd=IP.split()[3]
    result.append(p.apply_async(ssh_cmd,(host,port,user,passwd,cmd)))

p.close()

for res in result:
    res.get(timeout=35)

14.2.7. ssh并发(取文件状态并发送邮件)

#!/usr/bin/python
#encoding:utf8
#config file: ip.list

import paramiko
import multiprocessing
import smtplib
import sys,os,time,datetime,socket,re
from email.mime.text import MIMEText

# 配置文件(IP列表)
Conf = 'ip.list'
user_name = 'peterli'
user_pwd = 'passwd'
port = 22
PATH = '/home/peterli/'

# 设置服务器名称、用户名、密码以及邮件后缀
mail_host = "smtp.163.com"
mail_user = "xuesong"
mail_pass = "mailpasswd"
mail_postfix = "163.com"
mailto_list = ["272121935@qq.com","quanzhou722@163.com"]
title = 'file check'

DATE1=(datetime.datetime.now() + datetime.timedelta(days=-1) ).strftime('%Y%m%d')
file_path = '%s%s' %(PATH,DATE1)

def Ssh_Cmd(file_path,host_ip,user_name,user_pwd,port=22):

    s = paramiko.SSHClient()
    s.load_system_host_keys()
    s.set_missing_host_key_policy(paramiko.AutoAddPolicy())

    try:
        s.connect(hostname=host_ip,port=port,username=user_name,password=user_pwd)
        stdin,stdout,stderr = s.exec_command('stat %s' %file_path)
        stat_result = '%s%s' %(stdout.read(),stderr.read())
        if stat_result.find('No such file or directory') == -1:
            file_status = 'OK\t'
            stdin,stdout,stderr = s.exec_command('du -sh %s' %file_path)
            cmd1_result = '%s_%s' %(stat_result.split()[32],stat_result.split()[33].split('.')[0])
            cmd2_result = ('%s%s' %(stdout.read(),stderr.read())).split()[0]
        else:
            file_status = '未生成\t'
            cmd1_result = 'null'
            cmd2_result = 'null'
        q.put(['Login successful'])
        s.close()
    except socket.error:
        file_status = '主机或端口错误'
        cmd1_result = '-'
        cmd2_result = '-'
    except paramiko.AuthenticationException:
        file_status = '用户或密码错误'
        cmd1_result = '-'
        cmd2_result = '-'
    except paramiko.BadHostKeyException:
        file_status = 'Bad host key'
        cmd1_result = '-'
        cmd2_result = '-'
    except:
        file_status = 'ssh异常'
        cmd1_result = '-'
        cmd2_result = '-'
    r.put('%s\t-\t%s\t%s\t%s\t%s\n' %(time.strftime('%Y-%m-%d_%H:%M'),host_ip,file_status,cmd2_result,cmd1_result))

def Concurrent(Conf,file_path,user_name,user_pwd,port):
    # 执行总计
    total = 0
    # 读取配置文件
    f=open(Conf)
    list = f.readlines()
    f.close()
    # 并发执行
    process_list = []
    log_file = file('file_check.log', 'w')
    log_file.write('检查时间\t\t业务\tIP\t\t文件状态\t大小\t生成时间\n')
    for host_info in list:
        # 判断配置文件中注释行跳过
        if host_info.startswith('#'):
            continue
        # 取变量,其中任意变量未取到就跳过执行
        try:
            host_ip=host_info.split()[0].strip()
            #user_name=host_info.split()[1]
            #user_pwd=host_info.split()[2]
        except:
            log_file.write('Profile error: %s\n' %(host_info))
            continue
        #try:
        #    port=int(host_info.split()[3])
        #except:
        #    port=22
        total +=1
        p = multiprocessing.Process(target=Ssh_Cmd,args=(file_path,host_ip,user_name,user_pwd,port))
        p.start()
        process_list.append(p)
    for j in process_list:
        j.join()
    for j in process_list:
        log_file.write(r.get())

    successful = q.qsize()
    log_file.write('执行完毕。 总执行:%s 登录成功:%s 登录失败:%s\n' %(total,successful,total - successful))
    log_file.flush()
    log_file.close()

def send_mail(to_list, sub):
    me = mail_user + "<"+mail_user+"@"+mail_postfix+">"
    fp = open('file_check.log')
    msg = MIMEText(fp.read(),_charset="utf-8")
    fp.close()
    msg['Subject'] = sub
    msg['From'] = me
    msg['To'] = ";".join(to_list)
    try:
        send_smtp = smtplib.SMTP()
        send_smtp.connect(mail_host)
        send_smtp.login(mail_user, mail_pass)
        send_smtp.sendmail(me, to_list, msg.as_string())
        send_smtp.close()
        return True
    except Exception, e:
        print str(e)[1]
        return False

if __name__ == '__main__':
    q = multiprocessing.Queue()
    r = multiprocessing.Queue()
    Concurrent(Conf,file_path,user_name,user_pwd,port)
    if send_mail(mailto_list,title):
        print "发送成功"
    else:
        print "发送失败"