您好,登錄后才能下訂單哦!
學習堡壘機之前先來學習一個核心模塊paramiko,常見的Fabric和ansible等批量管理服務器工具都是基于paramiko模塊來實現(xiàn),或者說都是將paramiko模塊封裝后再進行相關改進。常用的功能有SSHClient和SFTPClient兩個類及其對應的方法:
先介紹SSHClient,它是paramiko模塊下的一個類,用于創(chuàng)建一個ssh連接對象,ssh可以通過基于密碼的認證登錄也可以基于秘鑰的登錄認證,接下來分兩種情況介紹:
①基于密碼的登錄認證
就創(chuàng)建了一個ssh對象
ssh = paramiko.SSHClient()
允許不在本地主機kown_hosts文件中的主機進行連接
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
創(chuàng)建一個基于ssh協(xié)議的連接主機的ssh連接
ssh.connect(hostname='10.0.0.13',port=22,username='opuser',password='123456')
執(zhí)行遠程命令
stdin,stdout,stderr = ssh.exec_command('df')
獲取執(zhí)行結果
result = stdout.read()
print result
關閉ssh連接
ssh.close()
范例1:
#!/usr/bin/env python
# -*- coding:utf8 -*-
# 導入paramiko模塊
import paramiko
# 通過類SSHClient實例化一個對象ssh
ssh = paramiko.SSHClient()
# 允許本地主機kown_hosts不存在的主機登錄
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 開啟一個ssh連接
ssh.connect(hostname='10.0.0.13',port=22,username='opuser',password='123456')
# 執(zhí)行shell命令df -Th
stdin,stdout,stderr = ssh.exec_command('df -Th')
# 讀取返回結果并打印到屏幕
print stdout.read()
# 關閉ssh連接
ssh.close()
②公鑰的登錄認證
定義指定的公鑰
private_key = paramiko.RSAKey.from_private_key_file('/home/opuser/.ssh/id_rsa')
就創(chuàng)建了一個ssh對象
ssh = paramiko.SSHClient()
允許不在本地主機kown_hosts文件中的主機進行連接
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
創(chuàng)建一個基于ssh協(xié)議的連接主機的ssh連接
ssh.connect(hostname='10.0.0.13',port=22,username='opuser',pkey=private_key)
執(zhí)行遠程命令
stdin,stdout,stderr = ssh.exec_command('df')
獲取執(zhí)行結果
result = stdout.read()
print result
關閉ssh連接
ssh.close()
【注:基于公鑰的登錄認證實現(xiàn)要將本地的公鑰拷貝到遠程主機的對應用戶家目錄下的.ssh/下,然后才可以實現(xiàn)免密碼登錄】
范例2:
# -*- coding:utf8 -*-
import paramiko #導入paramiko模塊
# 定義指定的公鑰
private_key = paramiko.RSAKey.from_private_key_file('/home/opuser/.ssh/id_rsa')
# 創(chuàng)建SSH對象
ssh = paramiko.SSHClient()
# 允許連接不在know_hosts文件中的主機
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 連接服務器
ssh.connect(hostname='10.0.0.13', port=22, username='opuser',pkey=private_key)
# 執(zhí)行命令
stdin, stdout, stderr = ssh.exec_command('df -Th')
# 讀取命令結果
result = stdout.read()
# 將獲取的結果輸出到屏幕
print result
由上面的介紹可以發(fā)現(xiàn)SSHClient類用于登錄遠程主機,那么SFTPClient類用來做啥呢?從字面意思不難發(fā)現(xiàn)跟sftp有關,在Linux下sftp是一個ftp程序,相當于windows下的ftp,所以SFTPClinet也應該可以實現(xiàn)對應的ftp功能,而ftp功能有哪些,我們平時用的最多的就是文件的上傳和下載,所以接下來介紹SFTPClinet的上傳和下載功能。跟SSHClinet類似,SFTPClinet也有兩種登錄認證:密碼和秘鑰
①基于密碼認證
# 導入paramiko模塊
import paramiko
# 實例化創(chuàng)建一個tranport對象通道(注意括號中的參數(shù)是一個元組)
transport = paramiko.Transport(('10.0.0.13', 22))
# 在transport通道中傳入用戶名和密碼創(chuàng)建一個ssh連接
transport.connect(username='opuser', password=‘123456’)
#創(chuàng)建一個sfp連接
sftp = paramiko.SFTPClient.from_transport(transport)
#定義本地文件及路徑
localfile='/lcsourece/localtion.py'
#定義遠端文件存放路徑
refile='/tmp/refile.py'
#將本地的文件localtion.py上傳到遠端/tmp/refile.py
sftp.put(localfile,refile)
#將遠端文件下載到本地
sftp.get('remoute_path','local_path')
#關閉ssh連接
transport.close()
②基于秘鑰的認證
#導入paramiko模塊
import paramiko
#定義私鑰地址
private_key = paramiko.RSAKey.from_private_key_file('/home/opuser/.ssh/id_rsa')
# 實例化創(chuàng)建一個tranport對象通道(注意括號中的參數(shù)是一個元組)
transport = paramiko.Transport(('10.0.0.13', 22))
# 在transport通道中傳入用戶名和秘鑰創(chuàng)建一個ssh連接
transport.connect(username='opuser', pkey=private_key)
#建立一個sftp連接
sftp=paramiko.SFTPClient.from_transport(transport)
# 將location.py 上傳至服務器 /tmp/test.py
sftp.put('/tmp/location.py', '/tmp/test.py')
# 將remove_path 下載到本地 local_path
sftp.get('remove_path', 'local_path')
#關閉sftp
transport.close()
面向對象封裝多個遠程操作
#看上面的paramiko執(zhí)行命令的時候有兩種方法,傳輸文件的時候有一種方法!并且這里在執(zhí)行命令的時候連接下然后關閉,傳輸文件的時候傳輸完后關閉,這樣不是很好!那么我們可以連接上,然后把執(zhí)行命令和上傳文件寫成兩個方法操作。另外在遠程執(zhí)行命令的時候其實是很快的但是他們消耗的時間基本上都在建立連接上了,所以我們要寫成連接上一次執(zhí)行命令或上傳文件全部都完事之后關閉。
#!/usr/bin/env python
# -*- coding:utf8 -*-
import paramiko
import uuid
class Haproxy(): #------->建立類Haproxy
def __init__(self):
self.host='10.0.0.13'
self.port=22
self.username='opuser'
self.password='123456'
def create_file(self): #創(chuàng)建文件方法
file_name=str(uuid.uuid4())#讀取uuid方法uuid4()生成的文件名
with open(file_name,'w') as f:
f.write('sb')
return file_name
def run(self):
self.connect()
self.upload()
self.rename()
self.close()
def connect(self):#設置連接方法
transport = paramiko.Transport((self.host,self.port))#創(chuàng)建一個連接對象
transport.connect(username=self.username,password=self.password)#調用transport對象中的連接方法
self.__transport = transport#把transport賦值給__transport
def close(self):#關閉連接
self.__transport.close()
def upload(self):#上傳文件方法
file_name = self.create_file()
sftp = paramiko.SFTPClient.from_transport(self.__transport)
sftp.put(file_name,'/home/opuser/ttttttt.py')
def rename(self):#執(zhí)行修改名字方法
ssh = paramiko.SSHClient()#建立ssh對象
ssh._transport = self.__transport#替換ssh_transport字段為self.__transport
stdin,stdout,stderr = ssh.exec_command('mv /home/opuser/ttttttt.py /home/opuser/oooooo.py')#執(zhí)行shell命令mv修改文件名
print stdout.read()#將執(zhí)行的命令的結果讀出來并返回輸出到屏幕
ha=Haproxy()
ha.run()
堡壘機的實現(xiàn)
堡壘機執(zhí)行流程:
管理員為用戶在服務器上創(chuàng)建賬號(將公鑰放置服務器,或者使用用戶名密碼)
用戶登陸堡壘機,輸入堡壘機用戶名密碼,現(xiàn)實當前用戶管理的服務器列表
用戶選擇服務器,并自動登陸
執(zhí)行操作并同時將用戶操作記錄
【注意:要想實現(xiàn)登錄就執(zhí)行腳本,可以在配置文件.bashrc中定義登錄后自動執(zhí)行腳本:如:/usr/bin/python /home/opuser/menu.py】
①實現(xiàn)用戶登錄
import getpass user = raw_input('username:') pwd = getpass.getpass('password') if user == 'alex' and pwd == '123': print '登陸成功' else: print '登陸失敗'
②根據(jù)用戶獲取相關服務器列表
dic = { 'alex': [ '10.0.0.10', '10.0.0.11', '10.0.0.12', ], 'eric': [ '10.0.0.14', ] } host_list = dic['alex'] print 'please select:' for index, item in enumerate(host_list, 1): print index, item inp = raw_input('your select (No):') inp = int(inp) hostname = host_list[inp-1] port = 22
③根據(jù)用戶名、私鑰登陸服務器
tran = paramiko.Transport((hostname, port,)) tran.start_client() default_path = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa') key = paramiko.RSAKey.from_private_key_file(default_path) tran.auth_publickey('opuser', key) # 打開一個通道 chan = tran.open_session() # 獲取一個終端 chan.get_pty() # 激活器 chan.invoke_shell() ######### # 利用sys.stdin,肆意妄為執(zhí)行操作 # 用戶在終端輸入內容,并將內容發(fā)送至遠程服務器 # 遠程服務器執(zhí)行命令,并將結果返回 # 用戶終端顯示內容 ######### chan.close() tran.close()
獲取一個Linux終端
#!/usr/bin/env python #-*- coding:utf-8 -*- import paramiko import os import sys import select import socket tran = paramiko.Transport(('10.0.0.13', 22,)) tran.start_client() ''' #使用密鑰認證 default_path = os.path.join(os.environ['opuser'], '.ssh', 'id_rsa') key = paramiko.RSAKey.from_private_key_file(default_path) tran.auth_publickey('opuser', key) ''' tran.auth_password('opuser', '123456!') #通過密碼認證 chan = tran.open_session()# 打開一個通道 chan.get_pty()# 獲取一個終端 chan.invoke_shell()# 激活器 ''' # 利用sys.stdin,肆意妄為執(zhí)行操作 # 用戶在終端輸入內容,并將內容發(fā)送至遠程服務器 # 遠程服務器執(zhí)行命令,并將結果返回 # 用戶終端顯示內容 ''' while True: # 監(jiān)視用戶輸入和服務器返回數(shù)據(jù) # sys.stdin 處理用戶輸入 # chan 是之前創(chuàng)建的通道,用于接收服務器返回信息 readable, writeable, error = select.select([chan, sys.stdin, ],[],[],1) #堅挺chen和終端 #只要發(fā)生變化,chan或者stdin或者都變化 if chan in readable: #遠端有變化后捕獲到 try: x = chan.recv(1024) #ssh連接后他發(fā)送接收數(shù)據(jù)也是通過socket來做的 if len(x) == 0: print '\r\n*** EOF\r\n', break sys.stdout.write(x)#把內容輸入到終端上 sys.stdout.flush() except socket.timeout: pass if sys.stdin in readable: #當終端有輸入捕獲到之后 inp = sys.stdin.readline() #把用戶的那一行輸入 chan.sendall(inp)#發(fā)送命令至遠端 chan.close() tran.close()
#上面的例子中在捕獲輸出的時候我們輸入的一行命令(字符串)回車之后,sys.stdin才捕獲到,這個是默認的終端是這樣的,我們就可以打開一個文件記錄用戶的所有命令操作
#!/usr/bin/env python #-*- coding:utf-8 -*- import paramiko import os import sys import select import socket tran = paramiko.Transport(('10.0.0.13', 22,)) tran.start_client() ''' #使用密鑰認證 default_path = os.path.join(os.environ['opuser'], '.ssh', 'id_rsa') key = paramiko.RSAKey.from_private_key_file(default_path) tran.auth_publickey('opuser', key) ''' tran.auth_password('opuser', '123456!') #通過密碼認證 chan = tran.open_session()# 打開一個通道 chan.get_pty()# 獲取一個終端 chan.invoke_shell()# 激活器 ''' # 利用sys.stdin,肆意妄為執(zhí)行操作 # 用戶在終端輸入內容,并將內容發(fā)送至遠程服務器 # 遠程服務器執(zhí)行命令,并將結果返回 # 用戶終端顯示內容 ''' log = open('record','ab') #打開一個文件記錄用戶的輸入 while True: # 監(jiān)視用戶輸入和服務器返回數(shù)據(jù) # sys.stdin 處理用戶輸入 # chan 是之前創(chuàng)建的通道,用于接收服務器返回信息 readable, writeable, error = select.select([chan, sys.stdin, ],[],[],1) #堅挺chen和終端 #只要發(fā)生變化,chan或者stdin或者都變化 if chan in readable: #遠端有變化后捕獲到 try: x = chan.recv(1024) #ssh連接后他發(fā)送接收數(shù)據(jù)也是通過socket來做的 if len(x) == 0: log.close() #關閉文件 print '\r\n************************ EOF ************************\r\n', break sys.stdout.write(x)#把內容輸入到終端上 sys.stdout.flush() except socket.timeout: pass if sys.stdin in readable: #當終端有輸入捕獲到之后 inp = sys.stdin.readline() #把用戶的那一行輸入 log.write(inp) #記錄命令 chan.sendall(inp)#發(fā)送命令至遠端 chan.close() tran.close()
#還有個例子是我們在終端輸入命令的時候,經(jīng)常忘記命令全部的字符。
#默認換行,對于特殊字符特殊處理,比如Ctrl+c
#改變終端默認由行+回車-->stdin,改為一個字符--> stdin
首先我們要做的就是修改終端模式:把原來的默認由“回車”換行和特殊字符特殊處理,改為輸入一個字符就捕獲到并且記錄到對應的日志文件,但是不記錄tab鍵
#!/usr/bin/env python #-*- coding:utf-8 -*- import paramiko import os import sys import select import socket import termios import tty tran = paramiko.Transport(('10.0.0.13', 22,)) tran.start_client() ''' #使用密鑰認證 default_path = os.path.join(os.environ['opuser'], '.ssh', 'id_rsa') key = paramiko.RSAKey.from_private_key_file(default_path) tran.auth_publickey('opuser', key) ''' tran.auth_password('opuser', '123456!') #通過密碼認證 chan = tran.open_session()# 打開一個通道 chan.get_pty()# 獲取一個終端 chan.invoke_shell()# 激活器 ''' # 利用sys.stdin,肆意妄為執(zhí)行操作 # 用戶在終端輸入內容,并將內容發(fā)送至遠程服務器 # 遠程服務器執(zhí)行命令,并將結果返回 # 用戶終端顯示內容 ''' # 獲取原tty屬性 oldtty = termios.tcgetattr(sys.stdin) try: # 為tty設置新屬性 # 默認當前tty設備屬性: # 輸入一行回車,執(zhí)行 # CTRL+C 進程退出,遇到特殊字符,特殊處理。 # 這是為原始模式,不認識所有特殊符號 # 放置特殊字符應用在當前終端,如此設置,將所有的用戶輸入均發(fā)送到遠程服務器 tty.setraw(sys.stdin.fileno()) #把遠端更換為LINUX原始模式 chan.settimeout(0.0) while True: # 監(jiān)視 用戶輸入 和 遠程服務器返回數(shù)據(jù)(socket) # 阻塞,直到句柄可讀 r, w, e = select.select([chan, sys.stdin], [], [], 1) if chan in r: try: x = chan.recv(1024) if len(x) == 0: print '\r\n*** EOF\r\n', break sys.stdout.write(x) sys.stdout.flush() except socket.timeout: pass if sys.stdin in r: x = sys.stdin.read(1) if len(x) == 0: break chan.send(x) finally: # 重新設置終端屬性 termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty) chan.close() tran.close()
最終修改版:
#!/usr/bin/env python #-*- coding:utf-8 -*- import paramiko import os import sys import select import socket import termios import tty tran = paramiko.Transport(('10.0.0.13', 22,)) tran.start_client() ''' #使用密鑰認證 default_path = os.path.join(os.environ['opuser'], '.ssh', 'id_rsa') key = paramiko.RSAKey.from_private_key_file(default_path) tran.auth_publickey('opuser', key) ''' tran.auth_password('opuser', '123456!') #通過密碼認證 chan = tran.open_session()# 打開一個通道 chan.get_pty()# 獲取一個終端 chan.invoke_shell()# 激活器 ''' # 利用sys.stdin,肆意妄為執(zhí)行操作 # 用戶在終端輸入內容,并將內容發(fā)送至遠程服務器 # 遠程服務器執(zhí)行命令,并將結果返回 # 用戶終端顯示內容 ''' # 獲取原tty屬性 oldtty = termios.tcgetattr(sys.stdin) #打開文件 try: # 為tty設置新屬性 # 默認當前tty設備屬性: # 輸入一行回車,執(zhí)行 # CTRL+C 進程退出,遇到特殊字符,特殊處理。 # 這是為原始模式,不認識所有特殊符號 # 放置特殊字符應用在當前終端,如此設置,將所有的用戶輸入均發(fā)送到遠程服務器 tty.setraw(sys.stdin.fileno()) #把遠端更換為LINUX原始模式 chan.settimeout(0.0) user_log = open('terminalnew_log','ab') while True: # 監(jiān)視 用戶輸入 和 遠程服務器返回數(shù)據(jù)(socket) # 阻塞,直到句柄可讀 r, w, e = select.select([chan, sys.stdin], [], [], 1) if chan in r: try: x = chan.recv(1024) if len(x) == 0: user_log.close() print '\r\n*** EOF\r\n', break sys.stdout.write(x) sys.stdout.flush() except socket.timeout: pass if sys.stdin in r: x = sys.stdin.read(1) if len(x) == 0: break if x == '\t': #判斷用戶的是否為tab如果為tab將不記錄 pass else: user_log.write(x)#如果用戶輸入的命令保存至日志 chan.send(x) finally: # 重新設置終端屬性 termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty) chan.close() tran.close()
Windows下打開終端
#!/usr/bin/env python #-*- coding:utf-8 -*- import paramiko import sys import threading tran = paramiko.Transport(('10.0.0.13', 22,)) tran.start_client() ''' #使用密鑰認證 default_path = os.path.join(os.environ['opuser'], '.ssh', 'id_rsa') key = paramiko.RSAKey.from_private_key_file(default_path) tran.auth_publickey('opuser', key) ''' tran.auth_password('opuser', '123456!') #通過密碼認證 chan = tran.open_session()# 打開一個通道 chan.get_pty()# 獲取一個終端 chan.invoke_shell()# 激活器 ''' # 利用sys.stdin,肆意妄為執(zhí)行操作 # 用戶在終端輸入內容,并將內容發(fā)送至遠程服務器 # 遠程服務器執(zhí)行命令,并將結果返回 # 用戶終端顯示內容 ''' sys.stdout.write("Line-buffered terminal emulation. Press F6 or ^Z to send EOF.\r\n\r\n") def writeall(sock): while True: data = sock.recv(256) ''' SSH發(fā)送數(shù)據(jù)的也是通過socket進行發(fā)送數(shù)據(jù)的,那么我們就可以使用socket來獲取遠程機器發(fā)送回來的數(shù)據(jù)。 while循環(huán)一直接收數(shù)據(jù),sock.recv(256)是阻塞的只有數(shù)據(jù)過來的時候才會繼續(xù)走。 ''' if not data: sys.stdout.write('\r\n*** EOF ***\r\n\r\n') sys.stdout.flush() break sys.stdout.write(data) sys.stdout.flush() writer = threading.Thread(target=writeall, args=(chan,)) #創(chuàng)建了一個線程,去執(zhí)行writeall方法,參數(shù)為chan(建立的SSH連接) writer.start() try: while True: #主線程循環(huán) d = sys.stdin.read(1) #一直監(jiān)聽用戶的輸入,輸入一個發(fā)送一個 if not d: break chan.send(d) except EOFError: # user hit ^Z or F6 pass chan.close() tran.close()
數(shù)據(jù)庫基本操作
Python操作MySQL模塊的安裝
linux:
yum install MySQL-python
windows:
http://files.cnblogs.com/files/wupeiqi/py-mysql-win.zip
SQL基本使用
1、數(shù)據(jù)庫操作
show databases;
use[databasename];
create database [name];
2、數(shù)據(jù)庫的表操作
show tables;
create table students
(
id int not null auto_increment primary key,
name char(8) not null,
sex char(4) not null,
age tinyint unsigned not null,
tel char(13) null default "-"
);
示例代碼:
CREATE TABLE `wb_blog` (
`id` smallint(8) unsigned NOT NULL,
`catid` smallint(5) unsigned NOT NULL DEFAULT '0',
`title` varchar(80) NOT NULL DEFAULT '',
`content` text NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `catename` (`catid`)
) ;
3、數(shù)據(jù)操作
insert into students(name,sex,age,tel) values('alex','man',18,'151515151')
delete from students where id =2;
update students set name = 'sb' where id =1;
select * from students
4、其他
主鍵
外鍵
左右連接
Python MySQL API
一、插入數(shù)據(jù)
import MySQLdb
conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='1234',db='mydb')
cur = conn.cursor()
reCount = cur.execute('insert into UserInfo(Name,Address) values(%s,%s)',('alex','usa'))
# reCount = cur.execute('insert into UserInfo(Name,Address) values(%(id)s, %(name)s)',{'id':12345,'name':'opuser'})
conn.commit()
cur.close()
conn.close()
print reCount
批量插入
import MySQLdb
conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='1234',db='mydb')
cur = conn.cursor()
li =[
('alex','usa'),
('sb','usa'),
]
reCount = cur.executemany('insert into UserInfo(Name,Address) values(%s,%s)',li)
conn.commit()
cur.close()
conn.close()
print reCount
注意:cur.lastrowid
二、刪除數(shù)據(jù)
import MySQLdb
conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='1234',db='mydb')
cur = conn.cursor()
reCount = cur.execute('delete from UserInfo')
conn.commit()
cur.close()
conn.close()
print reCount
四、查數(shù)據(jù)
# ############################## fetchone/fetchmany(num) ##############################
import MySQLdb
conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='1234',db='mydb')
cur = conn.cursor()
reCount = cur.execute('select * from UserInfo')
print cur.fetchone()
print cur.fetchone()
cur.scroll(-1,mode='relative')
print cur.fetchone()
print cur.fetchone()
cur.scroll(0,mode='absolute')
print cur.fetchone()
print cur.fetchone()
cur.close()
conn.close()
print reCount
# ############################## fetchall ##############################
import MySQLdb
conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='1234',db='mydb')
#cur = conn.cursor(cursorclass = MySQLdb.cursors.DictCursor)
cur = conn.cursor()
reCount = cur.execute('select Name,Address from UserInfo')
nRet = cur.fetchall()
cur.close()
conn.close()
print reCount
print nRet
for i in nRet:
print i[0],i[1]
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。