您好,登錄后才能下訂單哦!
學習堡壘機之前先來學習一個核心模塊paramiko,常見的Fabric和ansible等批量管理服務器工具都是基于paramiko模塊來實現,或者說都是將paramiko模塊封裝后再進行相關改進。常用的功能有SSHClient和SFTPClient兩個類及其對應的方法:
先介紹SSHClient,它是paramiko模塊下的一個類,用于創建一個ssh連接對象,ssh可以通過基于密碼的認證登錄也可以基于秘鑰的登錄認證,接下來分兩種情況介紹:
①基于密碼的登錄認證
就創建了一個ssh對象
ssh = paramiko.SSHClient()
允許不在本地主機kown_hosts文件中的主機進行連接
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
創建一個基于ssh協議的連接主機的ssh連接
ssh.connect(hostname='10.0.0.13',port=22,username='opuser',password='123456')
執行遠程命令
stdin,stdout,stderr = ssh.exec_command('df')
獲取執行結果
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')
# 執行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')
就創建了一個ssh對象
ssh = paramiko.SSHClient()
允許不在本地主機kown_hosts文件中的主機進行連接
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
創建一個基于ssh協議的連接主機的ssh連接
ssh.connect(hostname='10.0.0.13',port=22,username='opuser',pkey=private_key)
執行遠程命令
stdin,stdout,stderr = ssh.exec_command('df')
獲取執行結果
result = stdout.read()
print result
關閉ssh連接
ssh.close()
【注:基于公鑰的登錄認證實現要將本地的公鑰拷貝到遠程主機的對應用戶家目錄下的.ssh/下,然后才可以實現免密碼登錄】
范例2:
# -*- coding:utf8 -*-
import paramiko #導入paramiko模塊
# 定義指定的公鑰
private_key = paramiko.RSAKey.from_private_key_file('/home/opuser/.ssh/id_rsa')
# 創建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)
# 執行命令
stdin, stdout, stderr = ssh.exec_command('df -Th')
# 讀取命令結果
result = stdout.read()
# 將獲取的結果輸出到屏幕
print result
由上面的介紹可以發現SSHClient類用于登錄遠程主機,那么SFTPClient類用來做啥呢?從字面意思不難發現跟sftp有關,在Linux下sftp是一個ftp程序,相當于windows下的ftp,所以SFTPClinet也應該可以實現對應的ftp功能,而ftp功能有哪些,我們平時用的最多的就是文件的上傳和下載,所以接下來介紹SFTPClinet的上傳和下載功能。跟SSHClinet類似,SFTPClinet也有兩種登錄認證:密碼和秘鑰
①基于密碼認證
# 導入paramiko模塊
import paramiko
# 實例化創建一個tranport對象通道(注意括號中的參數是一個元組)
transport = paramiko.Transport(('10.0.0.13', 22))
# 在transport通道中傳入用戶名和密碼創建一個ssh連接
transport.connect(username='opuser', password=‘123456’)
#創建一個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')
# 實例化創建一個tranport對象通道(注意括號中的參數是一個元組)
transport = paramiko.Transport(('10.0.0.13', 22))
# 在transport通道中傳入用戶名和秘鑰創建一個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執行命令的時候有兩種方法,傳輸文件的時候有一種方法!并且這里在執行命令的時候連接下然后關閉,傳輸文件的時候傳輸完后關閉,這樣不是很好!那么我們可以連接上,然后把執行命令和上傳文件寫成兩個方法操作。另外在遠程執行命令的時候其實是很快的但是他們消耗的時間基本上都在建立連接上了,所以我們要寫成連接上一次執行命令或上傳文件全部都完事之后關閉。
#!/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): #創建文件方法
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))#創建一個連接對象
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):#執行修改名字方法
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')#執行shell命令mv修改文件名
print stdout.read()#將執行的命令的結果讀出來并返回輸出到屏幕
ha=Haproxy()
ha.run()
堡壘機的實現
堡壘機執行流程:
管理員為用戶在服務器上創建賬號(將公鑰放置服務器,或者使用用戶名密碼)
用戶登陸堡壘機,輸入堡壘機用戶名密碼,現實當前用戶管理的服務器列表
用戶選擇服務器,并自動登陸
執行操作并同時將用戶操作記錄
【注意:要想實現登錄就執行腳本,可以在配置文件.bashrc中定義登錄后自動執行腳本:如:/usr/bin/python /home/opuser/menu.py】
①實現用戶登錄
import getpass user = raw_input('username:') pwd = getpass.getpass('password') if user == 'alex' and pwd == '123': print '登陸成功' else: print '登陸失敗'
②根據用戶獲取相關服務器列表
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
③根據用戶名、私鑰登陸服務器
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,肆意妄為執行操作 # 用戶在終端輸入內容,并將內容發送至遠程服務器 # 遠程服務器執行命令,并將結果返回 # 用戶終端顯示內容 ######### 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,肆意妄為執行操作 # 用戶在終端輸入內容,并將內容發送至遠程服務器 # 遠程服務器執行命令,并將結果返回 # 用戶終端顯示內容 ''' while True: # 監視用戶輸入和服務器返回數據 # sys.stdin 處理用戶輸入 # chan 是之前創建的通道,用于接收服務器返回信息 readable, writeable, error = select.select([chan, sys.stdin, ],[],[],1) #堅挺chen和終端 #只要發生變化,chan或者stdin或者都變化 if chan in readable: #遠端有變化后捕獲到 try: x = chan.recv(1024) #ssh連接后他發送接收數據也是通過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)#發送命令至遠端 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,肆意妄為執行操作 # 用戶在終端輸入內容,并將內容發送至遠程服務器 # 遠程服務器執行命令,并將結果返回 # 用戶終端顯示內容 ''' log = open('record','ab') #打開一個文件記錄用戶的輸入 while True: # 監視用戶輸入和服務器返回數據 # sys.stdin 處理用戶輸入 # chan 是之前創建的通道,用于接收服務器返回信息 readable, writeable, error = select.select([chan, sys.stdin, ],[],[],1) #堅挺chen和終端 #只要發生變化,chan或者stdin或者都變化 if chan in readable: #遠端有變化后捕獲到 try: x = chan.recv(1024) #ssh連接后他發送接收數據也是通過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)#發送命令至遠端 chan.close() tran.close()
#還有個例子是我們在終端輸入命令的時候,經常忘記命令全部的字符。
#默認換行,對于特殊字符特殊處理,比如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,肆意妄為執行操作 # 用戶在終端輸入內容,并將內容發送至遠程服務器 # 遠程服務器執行命令,并將結果返回 # 用戶終端顯示內容 ''' # 獲取原tty屬性 oldtty = termios.tcgetattr(sys.stdin) try: # 為tty設置新屬性 # 默認當前tty設備屬性: # 輸入一行回車,執行 # CTRL+C 進程退出,遇到特殊字符,特殊處理。 # 這是為原始模式,不認識所有特殊符號 # 放置特殊字符應用在當前終端,如此設置,將所有的用戶輸入均發送到遠程服務器 tty.setraw(sys.stdin.fileno()) #把遠端更換為LINUX原始模式 chan.settimeout(0.0) while True: # 監視 用戶輸入 和 遠程服務器返回數據(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,肆意妄為執行操作 # 用戶在終端輸入內容,并將內容發送至遠程服務器 # 遠程服務器執行命令,并將結果返回 # 用戶終端顯示內容 ''' # 獲取原tty屬性 oldtty = termios.tcgetattr(sys.stdin) #打開文件 try: # 為tty設置新屬性 # 默認當前tty設備屬性: # 輸入一行回車,執行 # CTRL+C 進程退出,遇到特殊字符,特殊處理。 # 這是為原始模式,不認識所有特殊符號 # 放置特殊字符應用在當前終端,如此設置,將所有的用戶輸入均發送到遠程服務器 tty.setraw(sys.stdin.fileno()) #把遠端更換為LINUX原始模式 chan.settimeout(0.0) user_log = open('terminalnew_log','ab') while True: # 監視 用戶輸入 和 遠程服務器返回數據(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,肆意妄為執行操作 # 用戶在終端輸入內容,并將內容發送至遠程服務器 # 遠程服務器執行命令,并將結果返回 # 用戶終端顯示內容 ''' 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發送數據的也是通過socket進行發送數據的,那么我們就可以使用socket來獲取遠程機器發送回來的數據。 while循環一直接收數據,sock.recv(256)是阻塞的只有數據過來的時候才會繼續走。 ''' 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,)) #創建了一個線程,去執行writeall方法,參數為chan(建立的SSH連接) writer.start() try: while True: #主線程循環 d = sys.stdin.read(1) #一直監聽用戶的輸入,輸入一個發送一個 if not d: break chan.send(d) except EOFError: # user hit ^Z or F6 pass chan.close() tran.close()
數據庫基本操作
Python操作MySQL模塊的安裝
linux:
yum install MySQL-python
windows:
http://files.cnblogs.com/files/wupeiqi/py-mysql-win.zip
SQL基本使用
1、數據庫操作
show databases;
use[databasename];
create database [name];
2、數據庫的表操作
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、數據操作
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
一、插入數據
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
二、刪除數據
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
四、查數據
# ############################## 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]
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。