Contents
19.4. 系统批量运维管理器paramiko¶
19.4.1. 使用 Python 远程登陆服务器的最佳实践¶
https://juejin.im/post/6844904078057668615
pip安装
pip install paramiko
easy_install paramiko
源码安装
# yum -y install python-devel
# wget http://ftp.dlitz.net/pub/dlitz/crypto/pycrypto/pycrypto-2.6.tar.gz
# tar -zxvf pycrypto-2.6.tar.gz
# cd pycrypto-2.6
# python setup.py install
# cd ..
# wget https://pypi.python.org/packages/source/e/ecdsa/ecdsa-0.10.tar.gz --no-check-certificate
# tar -zxvf ecdsa-0.10.tar.gz
# cd ecdsa-0.10
# python setup.py install
# cd ..
# wget https://github.com/paramiko/paramiko/archive/v1.12.2.tar.gz
# tar -zxvf v1.12.2.tar.gz
# cd paramiko-1.12.2/
# python setup.py install
paramiko使用密码登录ssh方式
#!/usr/bin/env python
#-*- coding:utf8 -*-
# auther; 18793
# Date:2019/8/17 18:18
# filename: 01.使用密码登录ssh方式1.py
import paramiko
hostname='192.168.0.103'
username='root'
password='admin#123'
paramiko.util.log_to_file('syslogin.log')
ssh=paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=hostname,port=22,username=username,password=password,compress=True)
stdin,stdout,stderr=ssh.exec_command('free -m')
print stdout.read()
stdin,stdout,stderr=ssh.exec_command('ifconfig| grep inet|head -1|awk -F\' \' \'{print $2}\'')
print stdout.read()
ssh.close()
paramiko实现文件上传、下载、创建、删除
#!/usr/bin/env python
# -*- coding:utf8 -*-
# auther; 18793
# Date:2019/8/17 18:32
# filename: 02.实现文件上传、下载、创建、删除.py
import paramiko
username = 'root'
password = 'admin#123'
hostname = '192.168.0.103'
port = 22
try:
t = paramiko.Transport((hostname, port))
t.connect(username=username, password=password)
sftp = paramiko.SFTPClient.from_transport(t)
# 上传文件
sftp.put('/home/python-scripts/02.高级篇/02.系统批量运维管理器paramiko/syslogin.log',
'/home/syslogin.log')
# 下载文件
sftp.get('/home/vagrant_2.2.4_x86_64.rpm',
'/home/python-scripts/02.高级篇/02.系统批量运维管理器paramiko/vagrant_2.2.4_x86_64.rpm')
# 创建目录
sftp.mkdir("/home/python-scrpts", 0775) # 创建目录
# 删除目录
sftp.rmdir('/home/test1')
# 文件重命名
sftp.rename('/home/aaaa', '/home/aaaa_bak')
# 打印文件信息
print(sftp.stat('/home/apache-tomcat-8.5.37.tar.gz'))
# 打印目录列表
print(sftp.listdir('/home'))
t.close()
except Exception as e:
print(str(e))
应用示例
实现自动密钥登录方式
#!/usr/bin/env python
import paramiko
import os
hostname='192.168.1.21'
username='root'
paramiko.util.log_to_file('syslogin.log')
ssh=paramiko.SSHClient()
ssh.load_system_host_keys()
privatekey = os.path.expanduser('/home/key/id_rsa')
key = paramiko.RSAKey.from_private_key_file(privatekey)
ssh.connect(hostname=hostname,username=username,pkey = key)
stdin,stdout,stderr=ssh.exec_command('free -m')
print stdout.read()
ssh.close()
堡垒机示例
#!/usr/bin/env python
import paramiko
import os,sys,time
hostname="192.168.1.21"
username="root"
password="SKJh935yft#"
blip="192.168.1.23"
bluser="root"
blpasswd="SKJh935yft#"
port=22
passinfo='\'s password: '
paramiko.util.log_to_file('syslogin.log')
ssh=paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=blip,username=bluser,password=blpasswd)
#new session
channel=ssh.invoke_shell()
channel.settimeout(10)
buff = ''
resp = ''
channel.send('ssh '+username+'@'+hostname+'\n')
while not buff.endswith(passinfo):
try:
resp = channel.recv(9999)
except Exception,e:
print 'Error info:%s connection time.' % (str(e))
channel.close()
ssh.close()
sys.exit()
buff += resp
if not buff.find('yes/no')==-1:
channel.send('yes\n')
buff=''
channel.send(password+'\n')
buff=''
while not buff.endswith('# '):
resp = channel.recv(9999)
if not resp.find(passinfo)==-1:
print 'Error info: Authentication failed.'
channel.close()
ssh.close()
sys.exit()
buff += resp
channel.send('ifconfig\n')
buff=''
try:
while buff.find('# ')==-1:
resp = channel.recv(9999)
buff += resp
except Exception, e:
print "error info:"+str(e)
print buff
channel.close()
ssh.close()
堡垒机模式下的远程文件上传
#!/usr/bin/env python
import paramiko
import os,sys,time
hostname="192.168.1.21"
username="root"
password="SKJh935yft#"
blip="192.168.1.23"
bluser="root"
blpasswd="SKJh935yft#"
tmpdir="/tmp"
remotedir="/data"
localpath="/home/nginx_access.tar.gz"
tmppath=tmpdir+"/nginx_access.tar.gz"
remotepath=remotedir+"/nginx_access_hd.tar.gz"
port=22
passinfo='\'s password: '
paramiko.util.log_to_file('syslogin.log')
t = paramiko.Transport((blip, port))
t.connect(username=bluser, password=blpasswd)
sftp =paramiko.SFTPClient.from_transport(t)
sftp.put(localpath, tmppath)
sftp.close()
ssh=paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=blip,username=bluser,password=blpasswd)
#new session
channel=ssh.invoke_shell()
channel.settimeout(10)
buff = ''
resp = ''
channel.send('scp '+tmppath+' '+username+'@'+hostname+':'+remotepath+'\n')
while not buff.endswith(passinfo):
try:
resp = channel.recv(9999)
except Exception,e:
print 'Error info:%s connection time.' % (str(e))
channel.close()
ssh.close()
sys.exit()
buff += resp
if not buff.find('yes/no')==-1:
channel.send('yes\n')
buff=''
channel.send(password+'\n')
buff=''
while not buff.endswith('# '):
resp = channel.recv(9999)
if not resp.find(passinfo)==-1:
print 'Error info: Authentication failed.'
channel.close()
ssh.close()
sys.exit()
buff += resp
print buff
channel.close()
ssh.close()
代码示例
import sys
import paramiko
import time
ip_address = "192.168.2.106"
username = "student"
password = "training"
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.load_system_host_keys()
ssh_client.connect(hostname=ip_address,\
username=username, password=password)
print ("Successful connection", ip_address)
ssh_client.invoke_shell()
remote_connection = ssh_client.exec_command('cd Desktop; mkdir work\n')
remote_connection = ssh_client.exec_command('mkdir test_folder\n')
#print( remote_connection.read() )
ssh_client.close
ssh的代码示例
logger.py
#!/usr/bin/env python
"""
logger.py: provides logging methods
"""
# from python lib
import logging
import sys
import os
class Log:
"""
Singleton class to create log object
"""
def __new__(cls):
if not hasattr(cls, 'instance'):
cls.instance = super().__new__(cls)
return cls.instance
def initialise(self, logfile, level='DEBUG'):
logger = logging.getLogger('qcs')
logger.propagate = True
logger.setLevel(level)
# create stream handler
fh = logging.StreamHandler(open(logfile, "w"))
sh = logging.StreamHandler(sys.stdout)
# create formatter
formatter = logging.Formatter(
'%(asctime)s %(levelname)s %(message)s')
# add formatter to sh
fh.setFormatter(formatter)
sh.setFormatter(formatter)
# add sh to logger
logger.addHandler(sh)
logger.addHandler(fh)
self.logger = logger
return self.logger
def __repr__(self):
return "{}()".format(self.__class__.__name__)
def debug(self, *args, **kwargs):
self.logger.debug(*args, **kwargs)
def info(self, *args, **kwargs):
self.logger.info(*args, **kwargs)
def warn(self, *args, **kwargs):
self.logger.warn(*args, **kwargs)
def error(self, *args, **kwargs):
self.logger.error(*args, **kwargs)
def critical(self, *args, **kwargs):
self.logger.critical(*args, **kwargs)
if __name__ == '__main__':
print("Module loaded successfully")
if os.environ.get('USE_ROBOT_LOGGER', None) == "True":
from libs.log.logger import Log
log = Log()
else:
log = Log()
# some sample tests
logfile = "test_log.log"
log.initialise(logfile)
print("I'm not using any logger")
log.info("This is info line")
log.debug("This is debug line")
log.error("This is error line")
ssh_lib.py
#!/usr/bin/env python
# -*- coding:utf8 -*-
# auther: 18793
# Date:2021/11/26 10:13
# filename: ssh_lib.py
# from python lib
import os
import sys
import paramiko
import pexpect
import time
# from external lib
from scp import SCPClient
# from qcs-automation libs
from libs.log import Log
# create log object
log = Log()
# username = sys.argv[1]
class SshConn(object):
""" 一个ssh的类 """
def __init__(self, ip, user, password):
self.ip_address = ip
self.user = user
self.password = password
self.conn = None
def _init_connection(self):
"""
Initiate ssh connection
:return: None
"""
try:
self.conn = paramiko.SSHClient()
self.conn.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.conn.connect(self.ip_address, username=self.user,
password=self.password)
child = pexpect.spawn('ssh {}@{}'.format(self.user,
self.ip_address))
res = child.expect([pexpect.TIMEOUT, ' (yes/no)?'])
child.sendline('yes')
# This sleep will help for pexpect to work
time.sleep(5)
except Exception as e:
log.error("Unable to connect remote server")
def execute_command(self, cmd):
"""
Execute command
:param cmd: Command to be executed
:return: return tuple of (stdout, stderr)
"""
try:
if not isinstance(cmd, str):
cmd = ' '.join(arg for arg in cmd)
if not self.conn:
self._init_connection()
log.info("Executing command: {} on {}".format(cmd,
self.ip_address))
stdin, stdout, stderr = self.conn.exec_command(cmd)
try:
stdoutbuffer = stdout.read()
except Exception as e:
stdout = str(e)
try:
stderrbuffer = stderr.read()
except Exception as e:
stderr = str(e)
try:
if not isinstance(stdout, str):
status = stdout.channel.recv_exit_status()
else:
status = None
except Exception as e:
status = str(e)
if not isinstance(stdout, str):
stdout = stdoutbuffer.decode('utf8')
if not isinstance(stderr, str):
stderr = stderrbuffer.decode('utf8')
log.info("Command status: {}".format(status))
log.debug(stdout.splitlines())
return (status, stdout.splitlines(), stderr.splitlines())
except Exception as e:
log.error("Unable to connect remote server {}" \
.format(self.ip_address))
log.error(e)
if 'SSH session not active' in str(e):
log.info("Restablising connection on {}" \
.format(self.ip_address))
# re-establish connection and execute the command
self._init_connection()
self.execute_command(cmd)
return None, None, None
def scp_get(self, remotepath, localpath, recursive=False):
"""
Scp files/dir from SSH server
"""
self._init_connection()
scp = SCPClient(self.conn.get_transport(), buff_size=16384, socket_timeout=15.0)
try:
scp.get(remotepath, localpath, recursive, preserve_times=True)
except Exception as e:
log.info("Hit exception while scp_get from {} to {} on {}".format(
remotepath, localpath, self.ip_address))
log.info(e)
raise
return True
def scp_put(self, localpath, remotepath, recursive=False):
"""
Scp files/dir to SSH server
"""
self._init_connection()
scp = SCPClient(self.conn.get_transport())
try:
scp.put(localpath, remotepath, recursive)
except Exception as e:
log.info("Hit exception while scp_put from {} to {} on {}".format(
localpath, remotepath, self.ip_address))
log.info(e)
raise
return True
def copy_command(self, localpath, remotepath):
"""
copy file to remote server
:param localpath: local path of the file
:param remotepath: path where file should get copied
"""
try:
if not self.conn:
self._init_connection()
sftp = self.conn.open_sftp()
try:
log.info(sftp.stat(remotepath))
log.info("File exists {}".format(remotepath))
except IOError:
log.info("Copying file {} to {}".format(localpath, remotepath))
sftp.put(localpath, os.path.abspath(remotepath))
sftp.close()
except paramiko.SSHException as e:
log.error("Connection Error: {}".format(e))
if __name__ == '__main__':
print("Module loaded successfully.")
logfile = "test_log.log"
log.initialise(logfile)
hu = SshConn("172.16.60.236", "root", "admin#123")
# 复制文件到本地
hu.copy_command("./test_log.log", "/home/tst_log.log")
# 在远程环境执行命令
print(hu.execute_command("hostname"))
# 从远程拷贝文件到本地
hu.scp_get("/home/go_muke", ".", recursive=True)
# 从本地上传文件到远程
hu.scp_put("/home/aaa", "/home/", recursive=True)