新聞中心
純干貨!python 在運(yùn)維中的應(yīng)用 (一):批量 ssh/sftp
日常工作中需要大量、頻繁地使用ssh到服務(wù)器查看、拉取相關(guān)的信息或者對服務(wù)器進(jìn)行變更。目前公司大量使用的shell,但是隨著邏輯的復(fù)雜化、腳本管理的精細(xì)化,shell已經(jīng)不滿足日常需求,于是我嘗試整合工作中的需求,制作適合的工具。 由于管理制度的缺陷,我以工作流程為核心思考適合自己的運(yùn)維方式,提升工作效率,把時間留給更有價值的事情。 完整代碼在最后,請大家參考。
成都創(chuàng)新互聯(lián)一直在為企業(yè)提供服務(wù),多年的磨煉,使我們在創(chuàng)意設(shè)計,網(wǎng)絡(luò)營銷推廣到技術(shù)研發(fā)擁有了開發(fā)經(jīng)驗。我們擅長傾聽企業(yè)需求,挖掘用戶對產(chǎn)品需求服務(wù)價值,為企業(yè)制作有用的創(chuàng)意設(shè)計體驗。核心團(tuán)隊擁有超過十余年以上行業(yè)經(jīng)驗,涵蓋創(chuàng)意,策化,開發(fā)等專業(yè)領(lǐng)域,公司涉及領(lǐng)域有基礎(chǔ)互聯(lián)網(wǎng)服務(wù)成都棕樹機(jī)房、app軟件定制開發(fā)、手機(jī)移動建站、網(wǎng)頁設(shè)計、網(wǎng)絡(luò)整合營銷。
生產(chǎn):4000+物理服務(wù)器,近 3000 臺虛擬機(jī)。
開發(fā)環(huán)境:python3.6、redhat7.9,除了paramiko為第三方模塊需要自己安裝,其他的直接import即可。
批量執(zhí)行操作是一把雙刃劍。批量執(zhí)行操作可以提升工作效率,但是隨之而來的風(fēng)險不可忽略。
風(fēng)險案例如下:
掛載很多數(shù)據(jù)盤,通常先格式化硬盤,再掛載數(shù)據(jù)盤,最后再寫入將開機(jī)掛載信息寫入/etc/fstab文件。在批量lsblk檢查硬盤信息的時候發(fā)現(xiàn)有的系統(tǒng)盤在/sda有的在/sdm,如果不事先檢查機(jī)器相關(guān)配置是否一致直接按照工作經(jīng)驗去執(zhí)行批量操作,會很容易造成個人難以承受的災(zāi)難。
在執(zhí)行批量操作時按照慣例:格式化硬盤-掛載-開機(jī)掛載的順序去執(zhí)行,假設(shè)有的機(jī)器因為某些故障導(dǎo)致格式化硬盤沒法正確執(zhí)行。在處理這類問題的時候通常會先提取出失敗的ip,并再按照慣例執(zhí)行操作。運(yùn)維人員會很容易忽略開機(jī)掛載的信息已經(jīng)寫過了,導(dǎo)致復(fù)寫(這都是血和淚的教訓(xùn))。
所以,為了避免故障,提升工作效率,我認(rèn)為應(yīng)當(dāng)建立團(tuán)隊在工作上的共識,應(yīng)當(dāng)遵守以下原則:
當(dāng)然,代碼的規(guī)范也應(yīng)當(dāng)重視起來,不僅是為了便于審計,同時也需要便于溯源。我認(rèn)為應(yīng)當(dāng)注意以下幾點(diǎn):
1、ssh no existing session,sftp超時時間設(shè)置:
在代碼無錯的情況下大量ip出現(xiàn)No existing session,排查后定位在代碼的寫法上,下面是一個正確的示例。由于最開始沒考慮到ssh連接的幾種情況導(dǎo)致了重寫好幾遍。另外sftp的實(shí)例貌似不能直接設(shè)置連接超時時間,所以我采用了先建立ssh連接再打開sftp的方法。
2、sftp中的get()和put()方法僅能傳文件,不支持直接傳目錄:
不能直接傳目錄,那換個思路,遍歷路徑中的目錄和文件,先創(chuàng)建目錄再傳文件就能達(dá)到一樣的效果了。在paramiko的sftp中s方法可以獲取遠(yuǎn)程路徑中的文件、目錄信息。那么我們可以寫一個遞歸來遍歷遠(yuǎn)程路徑中的所有文件和目錄(傳入一個列表是為了接收遞歸返回的值)。
python自帶的os模塊中的os.walk()方法可以遍歷到本地路徑中的目錄和文件。
3、多線程多個ip使用s方法時無法并發(fā)。
改成多進(jìn)程即可。
4、多個ip需要執(zhí)行相同命令或不同的命令。
由于是日常使用的場景不會很復(fù)雜,所以借鑒了ansible的playbook,讀取提前準(zhǔn)備好的配置文件即可,然后再整合到之前定義的ssh函數(shù)中。
同時,我們還衍生出一個需求,既然都要讀取配置,那同樣也可以提前把ip地址準(zhǔn)備在文件里。正好也能讀取我們返回的執(zhí)行程序的結(jié)果。
參數(shù)說明:
密碼認(rèn)證:
公鑰認(rèn)證:
可以配合 grep,awk 等命令精準(zhǔn)過濾。
個人認(rèn)為 Python 在初中級運(yùn)維工作中的性質(zhì)更像是工具,以提升工作效率、減少管理成本為主??梢詮漠?dāng)前繁瑣的工作中解脫出來,去 探索 更有價值的事情。python 本質(zhì)上并不會減少故障的產(chǎn)生,所以在不同的階段合理利用自身掌握的知識解決當(dāng)前最重要的痛點(diǎn),千萬不要本末倒置。
如何使用Python 自動執(zhí)行連接ssh后并執(zhí)行Oracle查詢語句并返回查詢結(jié)果?
可以使用paramiko模塊,這個模塊就是python實(shí)現(xiàn)的高效ssh客戶端,用它連接遠(yuǎn)程服務(wù)器后,就可以使用里面的函數(shù)來執(zhí)行Oracle語句,返回結(jié)果可以保存為列表,然后打印出來就可以了,你可以嘗試一下,這里就不給出具體的代碼了。
如何用python開發(fā)一個ssh客戶端工具
1)通過paramiko的ssh模塊連接指定主機(jī);
2)?通過SSHClient.exec_command在遠(yuǎn)程主機(jī)上執(zhí)行命令;
3)通過exec_command返回的stdout,stdin,stderr進(jìn)行交互;
4)保存成功連接的主機(jī)信息(session),可以通過ls命令查看,?session?id命令,直接啟動新連接;
5)可在windows和linux下運(yùn)行,寫程序時需要注意他們的差別。
代碼ssh.py
#!/usr/bin/python
#?-*-?coding:?utf-8?-*-
import?os,sys
import?paramiko??
import?threading??
import?platform
curr_ssh?=?None?
curr_prompt?=?""
#使用說明???????
def?printUsage():
print?"????!ls?????????????????????:list?sessions."
print?"????!session?id?????????????:connect?session."
print?"????!conn?host?user?password:connect?host?with?user."
print?"????!exit???????????????????:exit."
#連接?
def?conn(ip,username,passwd):
try:
ssh?=?paramiko.SSHClient()??
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())??
ssh.connect(ip,22,username,passwd,timeout=5)??
print?"Connect?to?",ip,"?with?",username
global?curr_prompt
curr_prompt=username+"@"+ip+""
return?ssh
except:
return?None
#加載以前的連接信息
sessions=[]
def?loadSessions():
global?sessions
try:
f?=?open("sessions")
sessions?=?f.readlines()
f.close()
except:
pass
#執(zhí)行本地命令,ssh.py的命令???????
def?exe_cmd_local(cmd):
if(cmd?==?"!ls"):
loadSessions()
global?sessions
i=0
print?"Sessions:"
for?s?in?sessions:
print"[%d]?%s"?%(i,s)
i+=1
else:
vals?=?cmd.split('?')
if(vals[0]=="!session"):
id?=?(int)(vals[1])
if(idlen(sessions)):?os_name="platform.system()"?new_console_cmd=""?if(os_name="="?"linux"):=""?.=""?ssh.py=""?"=""?+=""?sessions[id]+"\""=""?elif(os_name="="?"windows"):=""?sessions[id]=""?os.system(new_console_cmd)=""?else:=""?print=""?"didn't=""?hava=""?sessoin=""?",vals[1]=""?elif(vals[0]="="!conn"):"?global=""?curr_ssh=""?f="open("sessions","a")"?line="vals[1]+""?"+vals[2]+"=""?"+vals[3]+"\n"=""?f.write(line)=""?f.close()=""?#在ssh連接的主機(jī)上執(zhí)行命令=""?def=""?exe_cmd_ssh(ssh,cmd):=""?if(ssh="="?none):=""?connect=""?to=""?a=""?server.=""?use=""?'!conn'=""?please."=""?return=""?stdin,=""?stdout,=""?stderr="ssh.exec_command(cmd)"?#stdin.write("y")=""?#簡單交互,輸入=""?‘y’=""?#屏幕輸出=""?stdout.read()=""?stderr.read()=""?#入口函數(shù)=""?if=""?__name__="='__main__':"?loadsessions()=""?if(len(sys.argv)="=4):"?printusage()=""?while=""?true:=""?cmd="raw_input(curr_prompt)"?if(len(cmd)="=0):"?continue=""?if(cmd="="?"!exit"):=""?if(curr_ssh=""?!="None):"?curr_ssh.close();=""?break=""?if(cmd[0]="="?'!'):=""?exe_cmd_local(cmd)=""?exe_cmd_ssh(curr_ssh,cmd)=""?pre=""
分享名稱:pythonssh函數(shù) python sse
標(biāo)題路徑:http://fisionsoft.com.cn/article/dogsegd.html