情境是這樣的:一個生產機房,會有很多的測試機器和生產機器(也就是30台左右吧),由於管理較為混亂導致了哪台機器有人用、哪台機器沒人用都不清楚,從而產生了一個想法--利用一台機器來管理所有的機器,記錄裝置責任人、裝置使用狀態等等資訊....那麼,為什麼選擇python,python足夠簡單並且擁有豐富的第三方庫的支援。
最初的想法
由於剛參加工作不久,對這些東西也都沒有接觸過,輪崗到某個部門需要做出點東西來(項目是什麼還沒情況,就要做出東西來,沒辦法硬著頭皮想點子吧)。。。
本想做一個簡單點的自動化測試的工具,但這項目的測試方法和測試案例暫時不能使用這種通用的測試手段(輸入和輸出都確定不了),從而作罷...
那麼做點什麼東西,經常發現同事們問208誰用的?201誰用的?那IP是我的!!!你是不是把我得網線給拔掉了?242那機器到底是哪台?
突然間,春天來了,是不是可以做一個系統用來檢測IP和記錄裝置的使用人,甚至可以按需要在某台裝置上運行一個指令碼或命令?把這個矮矬窮的想法和leader溝通過後,確認可以做,那麼就開始吧!!!
設計思想
該系統的大概思想:
1. 要獲得所有伺服器的各種資訊,需要在任意一台伺服器上部署一個agent作為資訊擷取的節點,定時向管理伺服器節點發送伺服器資訊資料。
2. server作為綜合管理節點,接收並儲存agent提交的資訊。
3. 為了方便使用,採用web頁面的形式做展示。
開發工具選擇
1. 開發語言:python
之所以選擇python,簡單,第三方庫豐富,不用造輪子
2. 資料庫:mysql
簡單、易用
3. webpy:web架構
入門簡單、部署方便
4. bootstrap:前端架構
不要關心太多前端問題
5. paramiko:python庫,遵循SSH2協議,支援以加密和認證的方式,進行遠程伺服器的串連
通過SSH方式串連agent伺服器:遠程運行命令、傳輸檔案
6. scapy: python庫,可用來發送、嗅探、解析和偽造網路資料包,這裡用來掃描IP
7. MySQLdb: 串連mysql
8. shell 和 python指令碼介面: 為其他人提供shell指令碼的介面
經驗分享
1. 前端對我來說是新東西,從來沒弄過,頁面的動畫效果,指令碼運行時的過渡都是需要考慮的,開始考慮利用倒計時,但是這個時間是不可控的,後來採用ajax來處理這個問題
2. agent要自動部署到每台機器,並可以通過server來控制重新整理時間
3. 建立一個可擴充的表是非常重要的,而且一些重要的資訊需要寫入磁碟,在資料庫失效的情況下,可以從磁碟擷取資料
4. 資料庫的串連,如果長時間沒有操作的話會逾時,要考慮到
... ...
項目結構--webpy
1. website.py為webpy的主程式,設定了url映射
2. model.py為webpy的url映射類,處理請求和返回
3. static中存放靜態資源
4. scripts用來存放處理的指令碼,這裡起的名字有些問題
串連資料庫
使用MyQSLdb串連mysql,在這裡我沒有使用webpy提供的資料庫介面,而是自己封裝了一套
ssh遠端連線伺服器
paramiko實現ssh串連、與資料轉送、執行命令和指令碼
複製代碼 代碼如下:
def executecmd(cmd, host, port=22, user='root', passwd='root'):
try:
s = paramiko.SSHClient()
s.set_missing_host_key_policy(paramiko.AutoAddPolicy())
s.connect(host, port, user, passwd, timeout = 10)
except Exception as e:
s.close()
print e
print 'connet error...'
return
try:
stdin,stdout,stderr=s.exec_command(cmd)
#print 'Host: %s......' %host
res = stdout.readlines()
except Exception as e:
print 'exec_commmand error...'
s.close()
return res
def executefile(file, host, port=22, user='root', passwd='root'):
try:
s = paramiko.SSHClient()
s.set_missing_host_key_policy(paramiko.AutoAddPolicy())
s.connect(host, port, user, passwd,timeout=5)
t = paramiko.Transport((host, port))
t.connect(username=user, password=passwd)
sftp =paramiko.SFTPClient.from_transport(t)
except Exception as e:
s.close()
print e
print 'connet error...'
return ''
try:
filename = os.path.basename(file)
if filename.find('.sh') >= 0:
sftp.put(path+'/'+file, '/tmp/tmp_test.sh')
stdin,stdout,stderr=s.exec_command('sh /tmp/tmp_test.sh 2>/dev/null', timeout=5)
else:
sftp.put(path+'/'+file, '/tmp/tmp_test.py')
stdin,stdout,stderr=s.exec_command('python /tmp/tmp_test.py', timeout=5)
#stdin,stdout,stderr=s.exec_command('rm -rf /tmp/tmp_test* 2>/dev/null')
res = stdout.readlines()
s.exec_command('rm -rf /tmp/tmp_test* 2>/dev/null')
except Exception as e:
s.exec_command('rm -rf /tmp/tmp_test* 2>/dev/null')
print 'timeout error...'
print e
return ''
return res
IP掃描
使用scapy進行IP掃描
複製代碼 代碼如下:
def pro(ip, cc, handle):
global dict
dst = ip + str(cc)
packet = IP(dst=dst, ttl=20)/ICMP()
reply = sr1(packet, timeout=TIMEOUT)
if reply:
print reply.src,' is online'
tmp = [1, reply.src]
handle.write(reply.src + '\n')
#handle.write(reply.src+" is online"+"\n")
def main():
threads=[]
ip = '192.168.1.1'
s = 2
e = 254
f=open('ip.log','w')
for i in range(s, e):
t=threading.Thread(target=pro,args=(ip,i,f))
threads.append(t)
print "main Thread begins at ",ctime()
for t in threads :
t.start()
for t in threads :
t.join()
print "main Thread ends at ",ctime()
大量新增ssh-key
複製代碼 代碼如下:
home_dir = '/home/xx'
id_rsa_pub = '%s/.ssh/id_rsa.pub' %home_dir
if not id_rsa_pub:
print 'id_rsa.pub Does not exist!'
sys.exit(0)
file_object = open('%s/.ssh/config' %home_dir ,'w')
file_object.write('StrictHostKeyChecking no\n')
file_object.write('UserKnownHostsFile /dev/null')
file_object.close()
def up_key(host,port,user,passwd):
try:
s = paramiko.SSHClient()
s.set_missing_host_key_policy(paramiko.AutoAddPolicy())
s.connect(host, port, user, passwd)
t = paramiko.Transport((host, port))
t.connect(username=user, password=passwd, timeout=3)
sftp =paramiko.SFTPClient.from_transport(t)
print 'create Host:%s .ssh dir......' %host
stdin,stdout,stderr=s.exec_command('mkdir ~/.ssh/')
print 'upload id_rsa.pub to Host:%s......' %host
sftp.put(id_rsa_pub, "/tmp/temp_key")
stdin,stdout,stderr=s.exec_command('cat /tmp/temp_key >> ~/.ssh/authorized_keys && rm -rf /tmp/temp_key')
print 'host:%s@%s auth success!\n' %(user, host)
s.close()
t.close()
except Exception, e:
#import traceback
#traceback.print_exc()
print 'connect error...'
print 'delete ' + host + ' from database...'
delip(host)
#delete from mysql****
try:
s.close()
t.close()
except:
pass