欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

使用Python編寫類UNIX系統(tǒng)的命令行工具的教程

系統(tǒng) 1636 0

引言

您是否能編寫命令行工具?也許您可以,但您能編寫出真正好用的命令行工具嗎?本文討論使用 Python 來創(chuàng)建一個(gè)強(qiáng)健的命令行工具,并帶有內(nèi)置的幫助菜單、錯(cuò)誤處理和選項(xiàng)處理。由于一些奇怪的原因,很多人并不了解 Python? 的標(biāo)準(zhǔn)庫具有制作功能極其強(qiáng)大的 *NIX 命令行工具所需的全部工具。

可以這樣說,Python 是制作 *NIX 命令行工具的最佳語言,因?yàn)樗勒铡癰atteries-included”的哲學(xué)方式工作,并且強(qiáng)調(diào)提供可讀性高的代碼。但僅作為提醒,當(dāng)您發(fā)現(xiàn)使用 Python 創(chuàng)建命令行工具是一件多么簡單的事情時(shí),這些想法很危險(xiǎn),您的生活可能被攪得一團(tuán)糟。據(jù)我所知,至今還沒有發(fā)表過詳細(xì)說明使用 Python 創(chuàng)建命令行工具的文章,因此我希望您喜歡這篇文章。
設(shè)置

Python 標(biāo)準(zhǔn)庫中的 optparse 模塊可完成創(chuàng)建命令行工具的大部分瑣碎工作。optparse 包含在 Python 2.3 中,因此該模塊將包括在許多 *NIX 操作系統(tǒng)中。如果由于某種原因,您使用的操作系統(tǒng)不包含所需要的模塊,那么值得慶幸的是,Python 的最新版本已經(jīng)過測試并編譯到幾乎任何 *NIX 操作系統(tǒng)中。Python 支持的系統(tǒng)包括 IBM? AIX?、HP-UX、Solaris、Free BSD、Red Hat Linux?、Ubuntu、OS X、IRIX,甚至包括幾種 Nokia 手機(jī)。
創(chuàng)建 Hello World 命令行工具

編寫優(yōu)秀的命令行工具的第一步是定義要解決的問題。這對您工具的成功至關(guān)重要。這對于以盡可能簡單的方法解決問題也同樣重要。這里明確地采用了 KISS(Keep It Simple Stupid,保持簡單)準(zhǔn)則。只有在實(shí)現(xiàn)并測試了計(jì)劃內(nèi)功能之后才添加選項(xiàng)和增加其他功能。

我們首先從創(chuàng)建 Hello World 命令行工具開始。按照上面的建議,我們使用盡可能簡單的術(shù)語來定義問題。

問題定義:我希望創(chuàng)建一個(gè)命令行工具,默認(rèn)打印 Hello World,并提供用于打印不通人的姓名的選項(xiàng)。

基于上述說明,可以提供一個(gè)包含少量代碼的解決方案。
Hello World 命令行接口 (CLI)

????????

            
 #!/usr/bin/env python
     import optparse
     
     def main():
      p = optparse.OptionParser()
      p.add_option('--person', '-p', default="world")
      options, arguments = p.parse_args()
      print 'Hello %s' % options.person
     
     if __name__ == '__main__':
      main()

          

如果運(yùn)行此代碼,預(yù)期的輸出如下:

            
Hello world


          

但是,我們通過少量代碼所能做到的遠(yuǎn)不止于此。我們可以獲得自動生成的幫助菜單:

            
python hello_cli.py --help  
     Usage: hello_cli.py [options]
     
     Options:
     -h, --help      show this help message and exit
     -p PERSON, --person=PERSON


          

從幫助菜單中可以了解到,我們可以使用兩種方法來更改 Hello World 的輸出:

            
python hello_cli.py -p guido
Hello guido


          

我們還實(shí)現(xiàn)了自動生成的錯(cuò)誤處理:

            
python hello_cli.py --name matz
Usage: hello_cli.py [options]
     
hello_cli.py: error: no such option: --name


          

如果您還沒有使用過 Python 的 optparse 模塊,那么您剛才可能會大吃一驚,并思忖使用 Python 可以編寫的所有這些不可思議的工具。如果您剛開始接觸 Python,那么您可能會驚訝于 Python 讓一切變得如此簡單。“XKCD”網(wǎng)站發(fā)表了關(guān)于“Python 是如此簡單”主題的非常有趣的漫畫,已包括在參考資料中。
創(chuàng)建有用的命令行工具

既然我們已經(jīng)打好了基礎(chǔ),我們就可以繼續(xù)創(chuàng)建解決特定問題的工具。對于本例,我們將使用 Python 的名為 Scapy 的網(wǎng)絡(luò)庫和交互式工具。Scapy 可以在大多數(shù) *NIX 系統(tǒng)上正常工作,可以在第 2 層和第 3 層上發(fā)送數(shù)據(jù)包,并允許您創(chuàng)建只有幾行 Python 代碼的非常復(fù)雜的工具。如果您希望按部就班從頭開始,請確保您正確地安裝了必要的軟件。

我們先定義要解決的新問題。

問題:我希望創(chuàng)建一個(gè)使用 IP 地址或子網(wǎng)作為參數(shù)的命令行工具,并向標(biāo)準(zhǔn)輸出返回 MAC 地址或 MAC 地址列表以及它們各自的 IP 地址。

既然我們已經(jīng)清楚地定義了問題,讓我嘗試將問題分解為盡可能簡單的部分,然后逐一解決這些部分。對于這一問題,我看到了兩個(gè)獨(dú)立的部分。第一部分是編寫接收 IP 地址或子網(wǎng)范圍的函數(shù),并返回 MAC 地址或 MAC 地址列表。我們可以在解決此問題之后再考慮將其集成到命令行工具中。
解決方案第 1 部分:創(chuàng)建通過 IP 地址確定 MAC 地址的 Python 函數(shù)

            
arping

from scapy import srp,Ether,ARP,conf

conf.verb=0
ans,unans=srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst="10.0.1.1"),
timeout=2)

for snd, rcv in ans:
print rcv.sprintf(r"%Ether.src% %ARP.psrc%")


          

該命令的輸出是:

            
    sudo python arping.py
    00:00:00:00:00:01 10.0.1.1


          

請注意,使用 scapy 執(zhí)行操作要求提升的權(quán)限,因此我們必須使用 sudo。考慮到本文的目的,我還將實(shí)際輸出更改為包括偽 MAC 地址。我們已經(jīng)證實(shí)了我們可以通過 IP 地址找到 MAC 地址。我們需要整理此代碼以接受 IP 地址或子網(wǎng)并返回 MAC 地址和 IP 地址對。
arping 函數(shù)

            
    #!/usr/bin/env python
    
    from scapy import srp,Ether,ARP,conf
    
    def arping(iprange="10.0.1.0/24"):
     conf.verb=0
     ans,unans=srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=iprange),
               timeout=2)
    
     collection = []
     for snd, rcv in ans:
      result = rcv.sprintf(r"%ARP.psrc% %Ether.src%").split()
      collection.append(result)
     return collection
    
    #Print results
    values = arping()
    
    for ip,mac in values:
    print ip,mac


          

正如您看到的,我們編寫了一個(gè)函數(shù),該函數(shù)接受 IP 地址或網(wǎng)絡(luò)并返回嵌套的 IP/MAC 地址列表。我們現(xiàn)已為第二部分做好準(zhǔn)備,為我們的工具創(chuàng)建一個(gè)命令行接口。
解決方案第 2 部分:從我們的 arping 函數(shù)創(chuàng)建命令行工具

在本例中,我們綜合本文前面部分的想法,創(chuàng)建一個(gè)能解決我們初始問題的完整命令行工具。
arping CLI

??

            
 #!/usr/bin/env python
  
  import optparse
  from scapy import srp,Ether,ARP,conf
  
  def arping(iprange="10.0.1.0/24"):
   """Arping function takes IP Address or Network, returns nested mac/ip list"""
  
   conf.verb=0
   ans,unans=srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=iprange),
        timeout=2)
  
   collection = []
   for snd, rcv in ans:
     result = rcv.sprintf(r"%ARP.psrc% %Ether.src%").split()
     collection.append(result)
   return collection
  
  def main():
   """Runs program and handles command line options"""
  
   p = optparse.OptionParser(description=' Finds MAC Address of IP address(es)',
                  prog='pyarping',
                  version='pyarping 0.1',
                  usage='%prog [10.0.1.1 or 10.0.1.0/24]')
  
  options, arguments = p.parse_args()
  if len(arguments) == 1:
   values = arping(iprange=arguments)
   for ip, mac in values:
    print ip, mac
  else:
   p.print_help()
  
  if __name__ == '__main__':
   main()

          

對以上腳本進(jìn)行幾點(diǎn)說明將有助于我們了解 optparse 的工作方式。

首先,必須創(chuàng)建 optparse.OptionParser() 的一個(gè)實(shí)例,并且接受如下所示的可選參數(shù):

?

復(fù)制代碼 代碼如下:
description, prog, version, and usage

這些參數(shù)的含義基本上可以不言自明,但我希望確認(rèn)的一點(diǎn)是,您應(yīng)該了解 optparse 雖然功能強(qiáng)大,但并不是無所不能。它具有明確定義的接口,可用于快速創(chuàng)建命令行工具。

其次,在如下行中:

復(fù)制代碼 代碼如下:
options, arguments = p.parse_args()

該行的作用是將選項(xiàng)和參數(shù)劃分為不同的位。在上述代碼中,我們預(yù)期恰有一個(gè)參數(shù),因此我指定必須只有一個(gè)參數(shù)值,并將該值傳遞給 arping 函數(shù)。

????

            
   if len(arguments) == 1:
      values = arping(iprange=arguments)

          

為了進(jìn)一步說明,讓我們運(yùn)行下面的命令以了解其工作方式:

            
     sudo python arping.py 10.0.1.1
     
     10.0.1.1 00:00:00:00:00:01


          

在上述示例中,參數(shù)為 10.0.1.1,由于正如我在條件語句中指定的那樣只有一個(gè)參數(shù),因此該參數(shù)被傳遞給 arping 函數(shù)。如果存在選項(xiàng),它們將在 options, arguments = p.parse_args() 方法中傳遞給 options。讓我們看一下,當(dāng)我們分解命令行工具的預(yù)期用例并賦予該用例兩個(gè)參數(shù)時(shí)將會發(fā)生什么情況:

            
     sudo python arping.py 10.0.1.1 10.0.1.3
     Usage: pyarping [10.0.1.1 or 10.0.1.0/24]
     
     Finds MAC Address or IP address(es)
     
     Options:
     --version  show program's version number and exit
     -h, --help show this help message and exit


          

根據(jù)我為參數(shù)構(gòu)建的條件語句的結(jié)構(gòu),如果參數(shù)的數(shù)目不為 1,它將自動打開幫助菜單:

            
     if len(arguments) == 1:
      values = arping(iprange=arguments)
      for ip, mac in values:
       print ip, mac
     else:
      p.print_help()


          

這是一種用于控制工具的工作方式的重要方法,因?yàn)槟梢允褂脜?shù)的個(gè)數(shù)或特定選項(xiàng)的名稱作為控制命令行工具的流程的機(jī)制。因?yàn)槲覀冊谧畛醯?Hello World 示例中涉及了選項(xiàng)的創(chuàng)建,接下來通過略微更改主函數(shù)向我們的命令行工具添加幾個(gè)選項(xiàng):
arping CLI main 函數(shù)

            
def main():
 """Runs program and handles command line options"""

 p = optparse.OptionParser(description='Finds MAC Address of IP address(es)',
              prog='pyarping',
              version='pyarping 0.1',
              usage='%prog [10.0.1.1 or 10.0.1.0/24]')
 p.add_option('-m', '--mac', action ='store_true', help='returns only mac address')
 p.add_option('-v', '--verbose', action ='store_true', help='returns verbose output')

 options, arguments = p.parse_args()
 if len(arguments) == 1:
  values = arping(iprange=arguments)
  if options.mac:
   for ip, mac in values:
    print mac
  elif options.verbose:
   for ip, mac in values:
    print "IP: %s MAC: %s " % (ip, mac)
  else:
   for ip, mac in values:
    print ip, mac

 else:
  p.print_help()


          

所做的主要更改是創(chuàng)建了基于是否指定了某個(gè)選項(xiàng)的條件語句。請注意,與 Hello World 命令行工具不同,我們僅使用選項(xiàng)作為我們工具的 true/false 信號。對于 ?CMAC 選項(xiàng)的情況,如果指定了該選項(xiàng),我們的條件語句 elif 將只打印 MAC 地址。

下面是新選項(xiàng)的輸出:
arping 輸出

            
     sudo python arping2.py 
     Password:
     Usage: pyarping [10.0.1.1 or 10.0.1.0/24]
     
     Finds MAC Address of IP address(es)
     
     Options:
     --version   show program's version number and exit
     -h, --help   show this help message and exit
     -m, --mac   returns only mac address
     -v, --verbose returns verbose output
     [ngift@M-6][H:11184][J:0]> sudo python arping2.py 10.0.1.1
     10.0.1.1 00:00:00:00:00:01
     [ngift@M-6][H:11185][J:0]> sudo python arping2.py -m 10.0.1.1
     00:00:00:00:00:01
     [ngift@M-6][H:11186][J:0]> sudo python arping2.py -v 10.0.1.1
     IP: 10.0.1.1 MAC: 00:00:00:00:00:01


          

深入學(xué)習(xí)創(chuàng)建命令行工具

下面是幾個(gè)用于深入學(xué)習(xí)的新想法。在我正與別人合著的有關(guān) Python *NIX 系統(tǒng)管理的書中對這些想法進(jìn)行了深入的探討,該書將在 2008 年中期出版。
在命令行工具中使用 subprocess 模塊

subprocess 模塊包括在 Python 2.4 或更高版本中,是用于處理系統(tǒng)調(diào)用和流程的統(tǒng)一接口。您可以輕松替換上面的 arping 函數(shù),以使用適用于您的特定 *NIX 操作系統(tǒng)的 arping 工具。以下是體現(xiàn)上述想法的粗略示例:
子流程 arping

            
  import subprocess
  import re
  def arping(ipaddress="10.0.1.1"):
   """Arping function takes IP Address or Network, returns nested mac/ip list"""
  
   #Assuming use of arping on Red Hat Linux
   p = subprocess.Popen("/usr/sbin/arping -c 2 %s" % ipaddress, shell=True,
              stdout=subprocess.PIPE)
   out = p.stdout.read()
   result = out.split()
   pattern = re.compile(":")
   for item in result:
    if re.search(pattern, item):
     print item
  arping()


          

以下是該函數(shù)單獨(dú)運(yùn)行時(shí)的輸出: [root@localhost]~# python pyarp.py [00:16:CB:C3:B4:10]

請注意使用 subprocess 來獲取 arping 命令的輸出,以及使用已編譯的正則表達(dá)式匹配 MAC 地址。注意,如果您使用的是 Python 2.3,則可以使用 popen 模塊替換 subprocess,后者在 Python 2.4 或更高版本中提供。
在命令行工具中使用對象關(guān)系映射器,如配合 SQLite 使用的 SQLAlchemy 或 Storm

命令行工具的另一個(gè)可能選項(xiàng)是使用 ORM(對象關(guān)系映射器)來存儲由命令行工具生成的數(shù)據(jù)記錄。有相當(dāng)多的 ORM 可用于 Python,但 SQLAlchemy 和 Storm 恰好是最常用的兩個(gè)。我通過擲硬幣的方式?jīng)Q定使用 Storm 作為示例:
Storm ORM arping

            
      #!/usr/bin/env python
      import optparse
      from storm.locals import *
      from scapy import srp,Ether,ARP,conf
      
      class NetworkRecord(object):
       __storm_table__ = "networkrecord"
       id = Int(primary=True)
       ip = RawStr()
       mac = RawStr()
       hostname = RawStr()
      
      def arping(iprange="10.0.1.0/24"):
       """Arping function takes IP Address or Network, 
       returns nested mac/ip list"""
      
       conf.verb=0
       ans,unans=srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=iprange),
              timeout=2)
       collection = []
       for snd, rcv in ans:
        result = rcv.sprintf(r"%ARP.psrc% %Ether.src%").split()
        collection.append(result)
       return collection
      
      def main():
       """Runs program and handles command line options"""
      
       p = optparse.OptionParser()
       p = optparse.OptionParser(description='Finds MACAddr of IP address(es)',
                    prog='pyarping',
                    version='pyarping 0.1',
                    usage= '%prog [10.0.1.1 or 10.0.1.0/24]')
      
       options, arguments = p.parse_args()
       if len(arguments) == 1:
        database = create_database("sqlite:")
        store = Store(database)
        store.execute("CREATE TABLE networkrecord "
           "(id INTEGER PRIMARY KEY, ip VARCHAR,\ 
           mac VARCHAR, hostname VARCHAR)")
        values = arping(iprange=arguments)
        machine = NetworkRecord()
        store.add(machine)
        #Creates Records
        for ip, mac in values:
         machine.mac = mac
         machine.ip = ip
        #Flushes to database
        store.flush()
        #Prints Record
        print "Record Number: %r" % machine.id
        print "MAC Address: %r" % machine.mac
        print "IP Address: %r" % machine.ip
       else:
        p.print_help()
      
      if __name__ == '__main__':
       main()


          

本例中需要關(guān)注的主要內(nèi)容是創(chuàng)建名為 NetworkRecord 的類,該類映射到“內(nèi)存中”的 SQLite 數(shù)據(jù)庫。在 main 函數(shù)中,我將 arping 函數(shù)的輸出更改為映射到我們的記錄對象,將它們更新到數(shù)據(jù)庫,然后再將其取回以打印結(jié)果。這明顯不是一個(gè)可用于生產(chǎn)的工具,但可作為在我們的工具中使用 ORM 的相關(guān)步驟的說明性示例。
在 CLI 中集成 config 文件
Python INI config 語法

            
     [AIX]
     MAC: 00:00:00:00:02
     IP: 10.0.1.2
     Hostname: aix.example.com
     [HPUX]
     MAC: 00:00:00:00:03
     IP: 10.0.1.3
     Hostname: hpux.example.com
     [SOLARIS]
     MAC: 00:00:00:00:04
     IP: 10.0.1.4
     Hostname: solaris.example.com
     [REDHAT]
     MAC: 00:00:00:00:05
     IP: 10.0.1.5
     Hostname: redhat.example.com
     [UBUNTU]
     MAC: 00:00:00:00:06
     IP: 10.0.1.6
     Hostname: ubuntu.example.com
     [OSX]
     MAC: 00:00:00:00:07
     IP: 10.0.1.7
     Hostname: osx.example.com


          

接下來,我們需要使用 ConfigParser 模塊來解析上述內(nèi)容:
ConfigParser 函數(shù)

            
     #!/usr/bin/env python
     import ConfigParser
     
     def readConfig(file="config.ini"):
      Config = ConfigParser.ConfigParser()
      Config.read(file)
      sections = Config.sections()
      for machine in sections:
       #uncomment line below to see how this config file is parsed
       #print Config.items(machine)
       macAddr = Config.items(machine)[0][1]
       print machine, macAddr
     readConfig()


          

該函數(shù)的輸出如下:

            
    OSX 00:00:00:00:07
    SOLARIS 00:00:00:00:04
    AIX 00:00:00:00:02
    REDHAT 00:00:00:00:05
    UBUNTU 00:00:00:00:06
    HPUX 00:00:00:00:03


          

我將剩下的問題作為練習(xí)留給讀者來解決。我接下來要做的是將該 config 文件集成到我的腳本中,這樣我就可以將我的 config 文件中記錄的機(jī)器庫存與出現(xiàn)在 ARP 緩存中的 MAC 地址的實(shí)際庫存進(jìn)行比較。IP 地址或主機(jī)名只在跟蹤到計(jì)算機(jī)時(shí)才能發(fā)揮其作用,但是我們實(shí)現(xiàn)的工具對于跟蹤網(wǎng)絡(luò)上存在的計(jì)算機(jī)的硬件地址并確定它以前是否出現(xiàn)在網(wǎng)絡(luò)上可能非常有用。

結(jié)束語

我們首先通過編寫幾行代碼創(chuàng)建了一個(gè)非常簡單但功能強(qiáng)大的 Hello World 命令行工具。然后使用 Python 網(wǎng)絡(luò)庫創(chuàng)建了一個(gè)復(fù)雜的網(wǎng)絡(luò)工具。最后,我們繼續(xù)討論一些更高級的研究領(lǐng)域以饗讀者。在高級研究部分,我們討論了 subprocess 模塊、對象關(guān)系映射器的集成,最后討論了配置文件。

雖然并不為眾人所知,但任何具有 IT 背景的讀者都可以使用 Python 輕松地創(chuàng)建命令行工具。我希望本文能夠激勵(lì)您親自動手創(chuàng)建全新的命令行工具。


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 91久久老司机福利精品网 | jizzjizz丝袜老师 | 亚洲国产三级 | 狠狠色噜噜狠狠狠狠米奇7777 | 亚州午夜| 久久这里只精品国产99热 | 欧美精彩视频 | 久久久青草 | 成人av网站免费观看 | 国产一精品一av一免费爽爽 | 国产视频在线看 | 亚洲精选久久 | 国产精品一区二区在线 | 91精品国啪老师啪 | 国产成人福利 | 日韩在线视频观看免费 | 777奇米影视色888成人 | 波多野结衣在线视频观看 | 狠狠干伊人网 | 2018天天操夜夜操 | 成年女人免费v片 | 插下面视频 | 日本视频在线播放 | 自拍偷拍亚洲视频 | 亚洲 欧美 校园 | 精品国产乱码一区二区三 | 日韩第一 | 国产精品无码人妻系列AV | 热久久伊人 | 欧美午夜视频 | 超级碰碰碰频视频免费观看 | www.夜色.com| 999久久久国产999久久久 | 色婷婷综合久久久中字幕精品久久 | av一区在线观看 | 涩涩色综合亚洲悠悠色 | 69p69永久网址 | 久久久久久久 | 色中色在线视频 | 国产在线日本 | 成人av免费观看 |