簡化除法判斷,分析apache訪問日誌,掃描存活主機,利用多線程實現ssh併發訪問

簡化除法判斷

1.1 問題

編寫mydiv.py腳本,主要要求以下:python

  • 提示用戶輸入一個數字做爲除數
  • 若是用戶按下Ctrl+C或Ctrl+D則退出程序
  • 若是用戶輸入非數字字符,提示用戶應該輸入數字
  • 若是用戶輸入0,提示用戶0不能做爲除數

1.2 方案

使用if語句判斷除數是否合適,須要編寫多條語句。有了異常處理,能夠本着先作,錯了再說的邏輯。直接把除法操做放在try語句中執行,根據產生的異常作相應的處理。程序員

另外,Ctrl+C或Ctrl+D只能經過異常捕獲。web

異常捕獲的語法以下:正則表達式

  1. try:
  2. A
  3. except:
  4. B
  5. else:
  6. C
  7. finally:
  8. D

把可能發生異常的語句放在A裏面執行,若是出現異常則執行B語句,沒有異常則執行C語句。無論是否出現異常都會執行D語句。shell

捕獲異常時,可使用多個except語句,每一個except語句捕獲一個異常,每一個異常給定不一樣的處理方法。也能夠把多個異常放在同一個except語句後面,可是務必注意,多個異常寫在相同的一行,必定要注括號括起來,放在元組中。apache

1.3 步驟

實現此案例須要按照以下步驟進行。編程

步驟一:編寫腳本vim

  1. #!/usr/bin/env python
  2. import sys
  3. while True:
  4. try:
  5. result = 100 / int(raw_input('enter a number: '))
  6. except (ValueError, ZeroDivisionError), e: #將異常緣由保存在變量e中
  7. print "invalid input:", e
  8. continue
  9. except (EOFError, KeyboardInterrupt):
  10. sys.exit(1)
  11. break
  12. print result

步驟二:測試腳本執行服務器

  1. [root@py01 bin]# ./mydiv.py
  2. enter a number: 0
  3. invalid input: integer division or modulo by zero
  4. enter a number: abc
  5. invalid input: invalid literal for int() with base 10: 'abc'
  6. enter a number: 3
  7. 33

2 案例2:分析apache訪問日誌

2.1 問題

編寫用於分析apache日誌的腳本,主要要求以下:多線程

  • 統計每一個客戶端訪問apache服務器的次數
  • 將統計信息經過字典的方式顯示出來
  • 分別統計客戶端是Firefox和MSIE的訪問次數
  • 分別使用函數式編程和麪向對象編程的方式實現

2.2 方案

涉及到文本處理時,正則表達式將是一個很是強大的工具。匹配客戶端的IP地址,可使用正則表達式的元字符,匹配字符串能夠直接使用字符的表面含義。

入門級程序員的寫法,使用順序的結構,直接編寫。這種方法雖然能夠得出結果,可是代碼難以重用。參考步驟一。

進階的寫法能夠採用函數式編程,方便往後再次使用。參考步驟二。

最後,還可使用OOP的編程方法,先定義一個統計類,該類將正則表達式做爲它的數據屬性。再定義一個方法,從指定的文件中搜索正則表達式出現的次數,並將其存入到一個字典中。參考步驟三。

2.3 步驟

實現此案例須要按照以下步驟進行。

步驟一:簡單實現

  1. [root@py01 bin]# vim countweb.py
  2. #!/usr/bin/env python
  3. import re
  4. logfile = '/var/log/httpd/access_log'
  5. cDict = {}
  6. patt_ip = '^\d+\.\d+\.\d+\.\d+' #定義匹配IP地址的正則表達式
  7. with open(logfile) as f:
  8. for eachLine in f:
  9. m = re.search(patt_ip, eachLine)
  10. if m is not None:
  11. ipaddr = m.group()
  12. #若是IP地址已在字典中,將其值加1,不然初始值設置爲1
  13. cDict[ipaddr] = cDict.get(ipaddr, 0) + 1
  14. print cDict

步驟二:使用函數式編程實現

  1. [root@py01 bin]# vim countweb2.py
  2. !/usr/bin/env python
  3. import re
  4. def countPatt(patt, fname): #定義能夠在指定文件中搜索指定字符串的函數
  5. cDict = {}
  6. with open(fname) as f:
  7. for eachLine in f:
  8. m = re.search(patt, eachLine)
  9. if m is not None:
  10. k = m.group()
  11. cDict[k] = cDict.get(k, 0) + 1
  12. return cDict
  13. def test():
  14. logfile = '/var/log/httpd/access_log'
  15. patt_ip = '^\d+\.\d+\.\d+\.\d+'
  16. print countPatt(patt_ip, logfile)
  17. patt_br = 'Firefox|MSIE'
  18. print countPatt(patt_br, logfile)
  19. if __name__ == '__main__':
  20. test()

3 案例3:掃描存活主機

3.1 問題

編寫掃描存活主機的腳本,主要要求以下:

  • 調用系統的ping命令進行掃描
  • 掃描教室環境下全部存活的主機
  • 採用多線程的方式編寫
  • 方案

os模塊的system()函數能夠調用系統命令,其返回值是系統命令退出碼,也就是若是系統命令成功執行,返回0,若是沒有成功執行,返回非零值。

本例掃描主機,能夠調用系統的ping命令,經過退出碼來判斷是否ping通了該主機。若是順序執行,每一個ping操做須要消耗數秒 鍾,所有的254個地址須要10分鐘以上。而採用多線程,能夠實現對這254個地址同時執行ping操做,併發的結果就是將執行時間縮短到了10秒鐘左 右。

3.2 步驟

實現此案例須要按照以下步驟進行。

步驟一:編寫腳本

  1. [root@py01 bin]# vim mtping.py
  2. #!/usr/bin/env python
  3. import subprocess
  4. import threading
  5. import sys
  6. def ping(ip):
  7. result = subprocess.call("ping -c2 %s &> /dev/null" % ip, shell=True)
  8. if result:
  9. print "%s:down" % ip
  10. else:
  11. print "%s:up" % ip
  12. if __name__ == '__main__':
  13. if len(sys.argv) != 2:
  14. print "Usage: %s subnet" % sys.argv[0]
  15. sys.exit(1)
  16. net_list = sys.argv[1].split('.')
  17. net = '.'.join(net_list[:-1])
  18. ips = ("%s.%s" % (net, i) for i in range(1, 255))
  19. for ip in ips:
  20. t = threading.Thread(target=ping, args=(ip,))
  21. t.start()

步驟二:測試腳本執行

  1. [root@py01 bin]# python mtping.py 172.40.51.0

腳本接受命令行參數,只要給定網段就能夠實現對該網段中全部ip地址的ping操做。

4 案例4:利用多線程實現ssh併發訪問

4.1 問題

編寫ssh客戶端腳本,主要要求以下:

  • 在文件中取出全部遠程主機IP地址
  • 在shell命令行中接受遠程服務器IP地址文件、遠程服務器密碼以及在遠程主機上執行的命令
  • 經過多線程實如今全部的遠程服務器上併發執行命令
  • 方案

python的paramiko模塊能夠實現ssh客戶端的功能,使用起來也比較簡單。可是當服務器很是多的時候,每臺服務器上執行徹底相同的簡單操做,也會花費大量的時間。

經過ssh加上多線程,能夠實現併發訪問。爲了將程序寫的靈活性更強,把要執行的命令以位置參數的方式來提供。

4.2 步驟

實現此案例須要按照以下步驟進行。

步驟一:編寫腳本

  1. [root@py01 bin]# vim remote_comm.py
  2. #!/usr/bin/env python
  3. import paramiko
  4. import os
  5. import sys
  6. import threading
  7. def remote_comm(host, password, comm):
  8. ssh = paramiko.SSHClient()
  9. ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  10. ssh.connect(host, username='root', password=password)
  11. stdin, stdout, stderr = ssh.exec_command(comm)
  12. out = stdout.read()
  13. err = stderr.read()
  14. if out:
  15. print "[%s:out]: %s" % (host, out),
  16. if err:
  17. print "%s:Error: %s", (host, err),
  18. ssh.close()
  19. if __name__ == '__main__':
  20. if len(sys.argv) != 4:
  21. print "Usage: %s ipfile password 'comm'" % sys.argv[0]
  22. sys.exit(1)
  23. ipfile = sys.argv[1]
  24. if not os.path.isfile(ipfile):
  25. print "No such file: %s" % ipfile
  26. sys.exit(2)
  27. password = sys.argv[2]
  28. comm = sys.argv[3]
  29. with open(ipfile) as fobj:
  30. for line in fobj:
  31. ip = line.strip()
  32. t = threading.Thread(target=remote_comm, args=(ip, password, comm))
  33. t.start()

步驟二:測試腳本執行

  1. [root@py01 bin]# python remote_comm.py ipaddr.txt tedu.cn 'useradd bob'
相關文章
相關標籤/搜索