Python 扫描存活主机

案例1:简化除法判断
案例2:分析apache访问日志
案例3:扫描存活主机
案例4:利用多线程实现ssh并发访问

1 案例1:简化除法判断
1.1 问题python

编写mydiv.py脚本,主要要求以下:程序员

提示用户输入一个数字做为除数
若是用户按下Ctrl+C或Ctrl+D则退出程序
若是用户输入非数字字符,提示用户应该输入数字
若是用户输入0,提示用户0不能做为除数

1.2 方案web

使用if语句判断除数是否合适,须要编写多条语句。有了异常处理,能够本着先作,错了再说的逻辑。直接把除法操做放在try语句中执行,根据产生的异常作相应的处理。正则表达式

另外,Ctrl+C或Ctrl+D只能经过异常捕获。shell

异常捕获的语法以下:apache

try:
    A
except:
    B
else:
    C
finally:
    D

把可能发生异常的语句放在A里面执行,若是出现异常则执行B语句,没有异常则执行C语句。无论是否出现异常都会执行D语句。编程

捕获异常时,可使用多个except语句,每一个except语句捕获一个异常,每一个异常给定不一样的处理方法。也能够把多个异常放在同一个except语句后面,可是务必注意,多个异常写在相同的一行,必定要注括号括起来,放在元组中。
1.3 步骤vim

实现此案例须要按照以下步骤进行。服务器

步骤一:编写脚本多线程

#!/usr/bin/env python
import  sys
while True:
    try:
        result = 100 / int(raw_input('enter a number: '))
    except (ValueError, ZeroDivisionError), e:   #将异常缘由保存在变量e中
        print "invalid input:", e
        continue
    except  (EOFError, KeyboardInterrupt):
        sys.exit(1)
    break
print  result

步骤二:测试脚本执行

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

2 案例2:分析apache访问日志
2.1 问题

编写用于分析apache日志的脚本,主要要求以下:

统计每一个客户端访问apache服务器的次数
将统计信息经过字典的方式显示出来
分别统计客户端是Firefox和MSIE的访问次数
分别使用函数式编程和面向对象编程的方式实现

2.2 方案

涉及到文本处理时,正则表达式将是一个很是强大的工具。匹配客户端的IP地址,可使用正则表达式的元字符,匹配字符串能够直接使用字符的表面含义。

入门级程序员的写法,使用顺序的结构,直接编写。这种方法虽然能够得出结果,可是代码难以重用。参考步骤一。

进阶的写法能够采用函数式编程,方便往后再次使用。参考步骤二。

最后,还可使用OOP的编程方法,先定义一个统计类,该类将正则表达式做为它的数据属性。再定义一个方法,从指定的文件中搜索正则表达式出现的次数,并将其存入到一个字典中。参考步骤三。
2.3 步骤

实现此案例须要按照以下步骤进行。

步骤一:简单实现

[root@py01 bin]# vim countweb.py
#!/usr/bin/env python
import re
logfile = '/var/log/httpd/access_log'
cDict = {}
patt_ip = '^\d+\.\d+\.\d+\.\d+'         #定义匹配IP地址的正则表达式
with open(logfile) as f:
    for eachLine in f:
        m = re.search(patt_ip, eachLine)
        if m is not None:
            ipaddr = m.group()
            #若是IP地址已在字典中,将其值加1,不然初始值设置为1
            cDict[ipaddr] = cDict.get(ipaddr, 0) + 1
print cDict

步骤二:使用函数式编程实现

[root@py01 bin]# vim countweb2.py
!/usr/bin/env python
import re
def countPatt(patt, fname):   #定义能够在指定文件中搜索指定字符串的函数
    cDict = {}
    with open(fname) as f:
        for eachLine in f:
            m = re.search(patt, eachLine)
            if m is not None:
                k = m.group()
                cDict[k] = cDict.get(k, 0) + 1
    return cDict
def test():
    logfile = '/var/log/httpd/access_log'
    patt_ip = '^\d+\.\d+\.\d+\.\d+'
    print countPatt(patt_ip, logfile)
    patt_br = 'Firefox|MSIE'
    print countPatt(patt_br, logfile)
if __name__ == '__main__':
    test()

3 案例3:扫描存活主机
3.1 问题

编写扫描存活主机的脚本,主要要求以下:

调用系统的ping命令进行扫描
扫描教室环境下全部存活的主机
采用多线程的方式编写
方案

os模块的system()函数能够调用系统命令,其返回值是系统命令退出码,也就是若是系统命令成功执行,返回0,若是没有成功执行,返回非零值。

本例扫描主机,能够调用系统的ping命令,经过退出码来判断是否ping通了该主机。若是顺序执行,每一个ping操做须要消耗数秒钟,所有的254个地址须要10分钟以上。而采用多线程,能够实现对这254个地址同时执行ping操做,并发的结果就是将执行时间缩短到了10秒钟左右。
3.2 步骤

实现此案例须要按照以下步骤进行。

步骤一:编写脚本

[root@py01 bin]# vim mtping.py
#!/usr/bin/env python
import subprocess
import threading
import sys
def ping(ip):
    result = subprocess.call("ping -c2 %s &> /dev/null" % ip, shell=True)
    if result:
        print "%s:down" % ip
    else:
        print "%s:up" % ip
if __name__ == '__main__':
    if len(sys.argv) != 2:
        print "Usage: %s subnet" % sys.argv[0]
        sys.exit(1)
    net_list = sys.argv[1].split('.')
    net = '.'.join(net_list[:-1])
    ips = ("%s.%s" % (net, i) for i in range(1, 255))
    for ip in ips:
        t = threading.Thread(target=ping, args=(ip,))
        t.start()

步骤二:测试脚本执行

[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 步骤

实现此案例须要按照以下步骤进行。

步骤一:编写脚本

[root@py01 bin]# vim remote_comm.py
#!/usr/bin/env python
import paramiko
import os
import sys
import threading
def remote_comm(host, password, comm):
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect(host, username='root', password=password)
    stdin, stdout, stderr = ssh.exec_command(comm)
    out = stdout.read()
    err = stderr.read()
    if out:
        print "[%s:out]: %s" % (host, out),
    if err:
        print "%s:Error: %s", (host, err),
    ssh.close()
if __name__ == '__main__':
    if len(sys.argv) != 4:
        print "Usage: %s ipfile password 'comm'" % sys.argv[0]
        sys.exit(1)
    ipfile = sys.argv[1]
    if not os.path.isfile(ipfile):
        print "No such file: %s" % ipfile
        sys.exit(2)
    password = sys.argv[2]
    comm = sys.argv[3]
    with open(ipfile) as fobj:
        for line in fobj:
            ip = line.strip()
            t = threading.Thread(target=remote_comm, args=(ip, password, comm))
            t.start()

步骤二:测试脚本执行

[root@py01 bin]# python remote_comm.py ipaddr.txt tedu.cn 'useradd bob'

脚本接受命令行参数,其中ipaddr.txt是存放全部远程主机ip地址的文件,文件中每一个ip地址占一行。tedu.cn是远程主机的密码(全部远程主机密码须要是一致的)。最后的命令须要写在引号中。

该示例执行成功后,会在全部远程主机上建立一个名为bob的用户。

相关文章
相关标签/搜索