欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

用Python制作檢測(cè)Linux運(yùn)行信息的工具的教程

 更新時(shí)間:2015年04月01日 09:24:34   作者:amitsaha  
這篇文章主要介紹了用Python制作檢測(cè)Linux運(yùn)行信息的工具的教程,主要是用CPython讀取運(yùn)行系統(tǒng)的硬件參數(shù)、網(wǎng)絡(luò)傳輸流量統(tǒng)計(jì)等,需要的朋友可以參考下

在這篇文章里,我們將會(huì)探索如何使用Python語(yǔ)言作為一個(gè)工具來(lái)檢測(cè)Linux系統(tǒng)各種運(yùn)行信息。讓我們一起來(lái)學(xué)習(xí)吧。

哪種Python?

當(dāng)我提到Python時(shí),我一般是指CPython 2(準(zhǔn)確來(lái)說(shuō)是2.7)。當(dāng)同樣的代碼不能在CPython3(3.3)運(yùn)行時(shí),我們明確地把它指出并給出替代的代碼,解釋它們之間的不同點(diǎn)。請(qǐng)確保你已經(jīng)安裝了CPython,在終端輸入python或者python3你會(huì)看到Python提示符出現(xiàn)在你的終端里。

請(qǐng)注意,所有的腳本程序都會(huì)以#!/usr/bin/env python作為第一行,意味著我們要Python解析器去運(yùn)行這些腳本。因此,如果你使用 chmod +x your-script.py 命令給你的腳本添加可執(zhí)行的權(quán)限,你可以使用./your-script.py命令直接運(yùn)行你的腳本(你將會(huì)在這篇文章里看到這種操作)

探索platform模塊

在標(biāo)準(zhǔn)庫(kù)中的platform模塊有大量的函數(shù)讓我們?nèi)z查各種系統(tǒng)信息。我們一起來(lái)打開(kāi)Python解釋器(譯者:直接在命令行輸入python即可打開(kāi))并探索其中的一部分函數(shù)。我們先從platform.uname()函數(shù)開(kāi)始:
 

>>> import platform
>>> platform.uname()
('Linux', 'fedora.echorand', '3.7.4-204.fc18.x86_64', '#1 SMP Wed Jan 23 16:44:29 UTC 2013', 'x86_64')

如果你知道Linux上的uname命令,你會(huì)意識(shí)到這個(gè)函數(shù)就是uname命令的一個(gè)接口。在Python 2,這個(gè)函數(shù)會(huì)返回一個(gè)由系統(tǒng)類型(或者內(nèi)核類型),主機(jī)名,版本號(hào),發(fā)行版號(hào),主機(jī)硬件架構(gòu)和處理器類型組成的元組。你可以使用索引來(lái)獲取單個(gè)屬性,像這樣:
 

>>> platform.uname()[0]
'Linux'

在Python 3,這個(gè)函數(shù)會(huì)返回一個(gè)默認(rèn)命名的元組:
 

>>> platform.uname()
 
uname_result(system='Linux', node='fedora.echorand',
release='3.7.4-204.fc18.x86_64', version='#1 SMP Wed Jan 23 16:44:29
UTC 2013', machine='x86_64', processor='x86_64')

因?yàn)榉祷刂凳莻€(gè)默認(rèn)命名的元組,所以我們可以輕易地通過(guò)變量名來(lái)獲取單個(gè)屬性而不用去記住各個(gè)屬性的下標(biāo),像這樣:
 

>>> platform.uname().system
'Linux'

platfrom模塊還提供了一些直接的接口來(lái)獲取上面的屬性值,像這些:
 

>>> platform.system()
'Linux'
 
>>> platform.release()
'3.7.4-204.fc18.x86_64'

函數(shù)linx_distribution()返回你正在使用的Linux發(fā)行版的詳細(xì)信息。舉個(gè)例子,在Fedora 18系統(tǒng)中,這條命令會(huì)返回下面的信息:
 

>>> platform.linux_distribution()
('Fedora', '18', 'Spherical Cow')

返回值是一個(gè)由發(fā)行版本名,版本號(hào),代號(hào)組成的元組。你可以通過(guò)_supported_dists屬性來(lái)打印你所用的Python版本支持哪些發(fā)行版本:
 

>>> platform._supported_dists
('SuSE', 'debian', 'fedora', 'redhat', 'centos', 'mandrake',
'mandriva', 'rocks', 'slackware', 'yellowdog', 'gentoo',
'UnitedLinux', 'turbolinux')

如果你的Linux發(fā)行版本不是上面那些的其中一個(gè)(或者是其中一個(gè)的衍生版),那么你調(diào)用上面的函數(shù)時(shí)不會(huì)看到任何有用的信息。

最后一個(gè)我們要探索的platfrom函數(shù)是architecture()函數(shù)。當(dāng)你不添加任何的參數(shù)來(lái)調(diào)用這個(gè)函數(shù)時(shí),這個(gè)函數(shù)會(huì)返回一個(gè)由位架構(gòu)和Python可執(zhí)行文件格式組成的元組。比如:
 

>>> platform.architecture()
('64bit', 'ELF')

在32位的Linux系統(tǒng)中,你會(huì)看到:
 

>>> platform.architecture()
('32bit', 'ELF')

如果你指定其他任意的系統(tǒng)可執(zhí)行程序作為參數(shù),你會(huì)得到類似的結(jié)果:
 

>>> platform.architecture(executable='/usr/bin/ls')
('64bit', 'ELF')

我們鼓勵(lì)你去探索platfrom模塊中的其他函數(shù),讓你找到你當(dāng)前使用的Python的版本。如果你非常想知道這個(gè)模塊是怎樣獲取這些信息的,你可以去看Python源代碼目錄下的Lib/platfrom.py文件。

os和sys模塊同樣是一個(gè)獲取統(tǒng)屬性的有用模塊就像本地BYTEORDER一樣。下一步,我們將會(huì)不使用Python你標(biāo)準(zhǔn)庫(kù)模塊來(lái)探索一些獲取Linux系統(tǒng)信息的通用方法,這次我們通過(guò)proc和sys文件系統(tǒng)來(lái)實(shí)現(xiàn)。要注意的是,通過(guò)這些文件系統(tǒng)獲取的信息在不同的硬件架構(gòu)里會(huì)有所不同。因此,在閱讀這篇文章和寫腳本從這些文件里獲取系統(tǒng)信息時(shí)要它記住。

CPU信息

/proc/cpuinfo這個(gè)文件包含了你系統(tǒng)的處理單元信息。比如,這里有一個(gè)與在命令行輸入cat /proc/cpuinfo 具備同樣功能的Python腳本
 

#! /usr/bin/env python
""" print out the /proc/cpuinfo
  file
"""
 
from __future__ import print_function
 
with open('/proc/cpuinfo') as f:
  for line in f:
    print(line.rstrip('n'))

當(dāng)你用Python 2或者Python 3運(yùn)行這個(gè)腳本時(shí),你會(huì)看到/proc/cpuinfo文件的所有內(nèi)容都在你的屏幕上顯示出來(lái)。(在上面這個(gè)腳本,rstrip()方法把每一行的換行符去掉)

下個(gè)代碼清單使用了startwith()這個(gè)字符串方法來(lái)顯示你電腦的處理單元型號(hào)
 

#! /usr/bin/env python
 
""" Print the model of your
  processing units
 
"""
 
from __future__ import print_function
 
with open('/proc/cpuinfo') as f:
  for line in f:
    # Ignore the blank line separating the information between
    # details about two processing units
    if line.strip():
      if line.rstrip('n').startswith('model name'):
        model_name = line.rstrip('n').split(':')[1]
        print(model_name)

當(dāng)你運(yùn)行這個(gè)腳本,你會(huì)看到你機(jī)器的所有處理單元的型號(hào)。比如,下面是我在我計(jì)算機(jī)里看到的:
 

Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz
Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz
Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz
Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz

到目前為止我們已經(jīng)有好幾種方法用來(lái)獲取我們的計(jì)算機(jī)系統(tǒng)構(gòu)架了。從技術(shù)的角度準(zhǔn)確地說(shuō),所有的這些方法實(shí)際上是呈現(xiàn)了你運(yùn)行的系統(tǒng)內(nèi)核的架構(gòu)。因此,如果你計(jì)算機(jī)實(shí)際上是64位的機(jī)器,但是運(yùn)行著32位的內(nèi)核,那么上面的方法將會(huì)顯現(xiàn)你的計(jì)算機(jī)是32位架構(gòu)的。為了找出計(jì)算機(jī)的正確架構(gòu),你可以查看在/proc/cpuinfo中的屬性列表的lm屬性。1m屬性代表著長(zhǎng)模式(Long mode)并且只會(huì)在64位架構(gòu)的計(jì)算機(jī)上出現(xiàn)。下面的腳本跟你展示是怎樣做的:

#! /usr/bin/env python
 
""" Find the real bit architecture
"""
 
from __future__ import print_function
 
with open('/proc/cpuinfo') as f:
  for line in f:
    # Ignore the blank line separating the information between
    # details about two processing units
    if line.strip():
      if line.rstrip('n').startswith('flags')
          or line.rstrip('n').startswith('Features'):
        if 'lm' in line.rstrip('n').split():
          print('64-bit')
        else:
          print('32-bit')

正如目前我們所看到的,我們能夠訪問(wèn)/proc/cpuinfo文件并且使用簡(jiǎn)單的文本處理技術(shù)去讀取我們?cè)诓檎业男畔?。為了友好地提供?shù)據(jù)給其他程序使用,最好的方法可能是把從/proc/cpuinfo里獲取的內(nèi)容轉(zhuǎn)換為標(biāo)準(zhǔn)的數(shù)據(jù)機(jī)構(gòu),比如轉(zhuǎn)換為字典類型。方法很簡(jiǎn)單:如果你看了這個(gè)文件,你會(huì)發(fā)現(xiàn)對(duì)于每一個(gè)處理單元都是以鍵值對(duì)形式存在(在之前的一個(gè)例子中,我們打印的處理器機(jī)型名時(shí),這里的model name就是一個(gè)鍵。)每個(gè)不同處理器單元的信息都會(huì)用空行來(lái)分開(kāi)。這使我們能方便地以每個(gè)處理單元數(shù)據(jù)為鍵來(lái)構(gòu)建字典數(shù)據(jù)結(jié)構(gòu)。這些鍵(key)都有一個(gè)值(value),每個(gè)值又對(duì)應(yīng)著每一個(gè)處理單元在/proc/cupinfo文件中的所有信息。下一個(gè)代碼清單告訴你怎樣做:

#!/usr/bin/env/ python
 
"""
/proc/cpuinfo as a Python dict
"""
from __future__ import print_function
from collections import OrderedDict
import pprint
 
def cpuinfo():
  ''' Return the information in /proc/cpuinfo
  as a dictionary in the following format:
  cpu_info['proc0']={...}
  cpu_info['proc1']={...}
 
  '''
 
  cpuinfo=OrderedDict()
  procinfo=OrderedDict()
 
  nprocs = 0
  with open('/proc/cpuinfo') as f:
    for line in f:
      if not line.strip():
        # end of one processor
        cpuinfo['proc%s' % nprocs] = procinfo
        nprocs=nprocs+1
        # Reset
        procinfo=OrderedDict()
      else:
        if len(line.split(':')) == 2:
          procinfo[line.split(':')[0].strip()] = line.split(':')[1].strip()
        else:
          procinfo[line.split(':')[0].strip()] = ''
 
  return cpuinfo
 
if __name__=='__main__':
  cpuinfo = cpuinfo()
  for processor in cpuinfo.keys():
    print(cpuinfo[processor]['model name'])

這段代碼使用了一個(gè)OrderedDict(有序的字典)代替常用的字典類型,目的是先對(duì)在文件中找到的鍵值對(duì)排序后再保存。因此,先展示第一個(gè)處理單元的數(shù)據(jù)信息其次是第二個(gè),以此類推。如果你調(diào)用這個(gè)函數(shù),它會(huì)返回一個(gè)字典類型給你。字典的每一個(gè)鍵都是一個(gè)處理單元。然后你可以使用鍵來(lái)篩選要找的信息(就像if __name='__main__'語(yǔ)句塊里展示的一樣)。當(dāng)上面的腳本運(yùn)行時(shí)會(huì)再次打印出每個(gè)處理單元的model name(通過(guò)print(cpuinfo[processor]['model name']語(yǔ)句來(lái)展示)
 

Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz
Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz
Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz
Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz

內(nèi)存信息

與/proc/cpuinfo類似,/proc/meminfo文件包含了你計(jì)算機(jī)的主存信息。下一個(gè)腳本產(chǎn)生一個(gè)包含這個(gè)文件內(nèi)容的字典并把它輸出。

#!/usr/bin/env python
 
from __future__ import print_function
from collections import OrderedDict
 
def meminfo():
  ''' Return the information in /proc/meminfo
  as a dictionary '''
  meminfo=OrderedDict()
 
  with open('/proc/meminfo') as f:
    for line in f:
      meminfo[line.split(':')[0]] = line.split(':')[1].strip()
  return meminfo
 
if __name__=='__main__':
  #print(meminfo())
 
  meminfo = meminfo()
  print('Total memory: {0}'.format(meminfo['MemTotal']))
  print('Free memory: {0}'.format(meminfo['MemFree']))

和前面看到的一樣,你同樣可以使用特定的鍵去獲取任意你想要的信息(在if __name__=='__main__'語(yǔ)句快里有展示)。當(dāng)你運(yùn)行這個(gè)腳本,你可以看到類似下面的輸出:
 

Total memory: 7897012 kB
Free memory: 249508 kB

網(wǎng)絡(luò)統(tǒng)計(jì)

下面,我們會(huì)探索我們計(jì)算機(jī)系統(tǒng)的網(wǎng)絡(luò)設(shè)備。我們將會(huì)檢索系統(tǒng)的網(wǎng)絡(luò)接口和系統(tǒng)開(kāi)啟后發(fā)送和接收到的字節(jié)數(shù)據(jù)。這些信息可以在/proc/net/dev文件中獲取。如果你審查過(guò)這個(gè)文件的內(nèi)容,你會(huì)發(fā)現(xiàn)前兩行包含了頭信息-i.e.文件中的第一列是網(wǎng)絡(luò)接口名,第二和第三列展示了接收和傳輸?shù)淖止?jié)信息(比如,總發(fā)送字節(jié),數(shù)據(jù)包數(shù)量,錯(cuò)誤統(tǒng)計(jì),等等)。我們感興趣的是如何獲取不同的網(wǎng)絡(luò)設(shè)備的總數(shù)據(jù)發(fā)送和接受量。下一個(gè)代碼清單展示了我們?nèi)绾螐?proc/net/dev提出這些信息:

#!/usr/bin/env python
from __future__ import print_function
from collections import namedtuple
 
def netdevs():
  ''' RX and TX bytes for each of the network devices '''
 
  with open('/proc/net/dev') as f:
    net_dump = f.readlines()
 
  device_data={}
  data = namedtuple('data',['rx','tx'])
  for line in net_dump[2:]:
    line = line.split(':')
    if line[0].strip() != 'lo':
      device_data[line[0].strip()] = data(float(line[1].split()[0])/(1024.0*1024.0),
                        float(line[1].split()[8])/(1024.0*1024.0))
 
  return device_data
 
if __name__=='__main__':
 
  netdevs = netdevs()
  for dev in netdevs.keys():
    print('{0}: {1} MiB {2} MiB'.format(dev, netdevs[dev].rx, netdevs[dev].tx))

當(dāng)你運(yùn)行上面的腳本時(shí),會(huì)以MiB為單位輸出從你最近的一次重啟后你的網(wǎng)絡(luò)設(shè)備接受和發(fā)送的數(shù)據(jù)。正如下面展示的:
 

em1: 0.0 MiB 0.0 MiB
wlan0: 2651.40951061 MiB 183.173976898 MiB

你可能會(huì)利用一個(gè)持久性存儲(chǔ)機(jī)制和這個(gè)腳本來(lái)寫一個(gè)你自己的數(shù)據(jù)使用監(jiān)控程序。

進(jìn)程

/proc目錄同樣包含了每個(gè)運(yùn)行進(jìn)程的目錄。這些目錄的名稱以相應(yīng)的進(jìn)程ID來(lái)命名。因此,如果你遍歷/proc目錄下的所有以數(shù)字命名的目錄,你會(huì)得到一個(gè)所有當(dāng)前運(yùn)行進(jìn)程的ID列表。下面的代碼清單里的process_list()函數(shù)返回一個(gè)包含所有當(dāng)前運(yùn)行進(jìn)程ID的列表。這個(gè)列表的長(zhǎng)度等于系統(tǒng)運(yùn)行進(jìn)程的總數(shù),正如你運(yùn)行這個(gè)腳本看到的一樣:
 

#!/usr/bin/env python
"""
 List of all process IDs currently active
"""
 
from __future__ import print_function
import os
def process_list():
 
  pids = []
  for subdir in os.listdir('/proc'):
    if subdir.isdigit():
      pids.append(subdir)
 
  return pids
 
if __name__=='__main__':
 
  pids = process_list()
  print('Total number of running processes:: {0}'.format(len(pids)))

運(yùn)行上面的腳本時(shí),輸出結(jié)果和下面輸出類似:

每個(gè)進(jìn)程目錄都包含了大量的其他文件和目錄,這些目錄包含了各種關(guān)于進(jìn)程調(diào)用命令,使用的共享庫(kù)和其他的信息。

塊設(shè)備

接下來(lái)的腳本通過(guò)訪問(wèn)sysfs虛擬文件系統(tǒng)列出了所有的塊設(shè)備信息。你能夠在/sys/block目錄下找到系統(tǒng)上的所有塊設(shè)備。因此,你的系統(tǒng)上會(huì)有/sys/block/sda,/sys/block/sdb和其他的類似目錄。為了找到這些設(shè)備,我們可以遍歷/sys/block目錄然后通過(guò)簡(jiǎn)單的正則表達(dá)式去匹配我們要查找的內(nèi)容。

#!/usr/bin/env python
 
"""
Read block device data from sysfs
"""
 
from __future__ import print_function
import glob
import re
import os
 
# Add any other device pattern to read from
dev_pattern = ['sd.*','mmcblk*']
 
def size(device):
  nr_sectors = open(device+'/size').read().rstrip('n')
  sect_size = open(device+'/queue/hw_sector_size').read().rstrip('n')
 
  # The sect_size is in bytes, so we convert it to GiB and then send it back
  return (float(nr_sectors)*float(sect_size))/(1024.0*1024.0*1024.0)
 
def detect_devs():
  for device in glob.glob('/sys/block/*'):
    for pattern in dev_pattern:
      if re.compile(pattern).match(os.path.basename(device)):
        print('Device:: {0}, Size:: {1} GiB'.format(device, size(device)))
 
if __name__=='__main__':
  detect_devs()

如果你運(yùn)行了這個(gè)腳本,你將會(huì)看到與下面類似的輸出結(jié)果:
 

Device:: /sys/block/sda, Size:: 465.761741638 GiB
Device:: /sys/block/mmcblk0, Size:: 3.70703125 GiB

當(dāng)我運(yùn)行這個(gè)腳本時(shí),我額外插入了一張SD卡。所以你會(huì)看到這個(gè)腳本檢測(cè)到了它(上面輸出的第二行,譯者注)。你同樣可以擴(kuò)展這個(gè)腳本去識(shí)別其他的塊設(shè)備(比如虛擬硬盤)。

構(gòu)建命令行工具

允許用戶指定命令行參數(shù)去自定義程序的默認(rèn)行為是所有Linux命令行工具的一個(gè)普遍特征。argparse模塊能使你程序擁有與內(nèi)置工具界面類似的界面。下一個(gè)代碼清單展示了一個(gè)獲取你系統(tǒng)上所有用戶并把它們相應(yīng)的登陸shell打印出來(lái)的程序。

#!/usr/bin/env python
 
"""
Print all the users and their login shells
"""
 
from __future__ import print_function
import pwd
 
# Get the users from /etc/passwd
def getusers():
  users = pwd.getpwall()
  for user in users:
    print('{0}:{1}'.format(user.pw_name, user.pw_shell))
 
if __name__=='__main__':
  getusers()

當(dāng)運(yùn)行上面的腳本時(shí),它會(huì)打印出你系統(tǒng)上所有的用戶和它們的登陸shell

現(xiàn)在,我們假設(shè)你想讓腳本使用者能夠選擇是否想看到系統(tǒng)的其他用戶(比如daemon,apache)。我們通過(guò)使用argparse模塊擴(kuò)展之前的代碼來(lái)實(shí)現(xiàn)這個(gè)功能,就像下面的代碼。

#!/usr/bin/env python
 
"""
Utility to play around with users and passwords on a Linux system
"""
 
from __future__ import print_function
import pwd
import argparse
import os
 
def read_login_defs():
 
  uid_min = None
  uid_max = None
 
  if os.path.exists('/etc/login.defs'):
    with open('/etc/login.defs') as f:
      login_data = f.readlines()
 
    for line in login_data:
      if line.startswith('UID_MIN'):
        uid_min = int(line.split()[1].strip())
 
      if line.startswith('UID_MAX'):
        uid_max = int(line.split()[1].strip())
 
  return uid_min, uid_max
 
# Get the users from /etc/passwd
def getusers(no_system=False):
 
  uid_min, uid_max = read_login_defs()
 
  if uid_min is None:
    uid_min = 1000
  if uid_max is None:
    uid_max = 60000
 
  users = pwd.getpwall()
  for user in users:
    if no_system:
      if user.pw_uid >= uid_min and user.pw_uid <= uid_max:
        print('{0}:{1}'.format(user.pw_name, user.pw_shell))
    else:
      print('{0}:{1}'.format(user.pw_name, user.pw_shell))
 
if __name__=='__main__':
 
  parser = argparse.ArgumentParser(description='User/Password Utility')
 
  parser.add_argument('--no-system', action='store_true',dest='no_system',
            default = False, help='Specify to omit system users')
 
  args = parser.parse_args()
  getusers(args.no_system)

使用–help選項(xiàng)來(lái)運(yùn)行上面的腳本,你會(huì)看到一個(gè)帶有可選項(xiàng)(和作用)的友好幫助信息
 

$ ./getusers.py --help
usage: getusers.py [-h] [--no-system]
 
User/Password Utility
 
optional arguments:
 -h, --help  show this help message and exit
 --no-system Specify to omit system users

上面腳本的一個(gè)例子調(diào)用如下:
 

$ ./getusers.py --no-system
gene:/bin/bash

當(dāng)你傳遞一個(gè)無(wú)效的參數(shù)時(shí),腳本會(huì)報(bào)錯(cuò):
 

$ ./getusers.py --param
usage: getusers.py [-h] [--no-system]
getusers.py: error: unrecognized arguments: --param

讓我們一起來(lái)簡(jiǎn)單地了解下在上面的腳本中我們是如何使用argparse模塊的parser=argparse.ArgumentParser(description='User/Password Utility')這行代碼使用一個(gè)描述腳本作用的可選參數(shù)創(chuàng)建了一個(gè)新的ArgumentParser對(duì)象。

然后,我們?cè)谙乱恍写a:parser.add_argument(‘–no-system', action='store_true', dest='no_system', default = False, help='Specify to omit system users')里使用了add_argument()方法添加一些參數(shù),讓腳本能夠識(shí)別命令行選項(xiàng)。這個(gè)方法的第一個(gè)參數(shù)是腳本使用者在調(diào)用腳本時(shí)作為參數(shù)提供的選項(xiàng)名。下一個(gè)參數(shù)action=store_true表明了這是一個(gè)布爾選項(xiàng)。也就是說(shuō)這個(gè)參數(shù)的有無(wú)在一定程度上會(huì)對(duì)程序產(chǎn)生影響。dest參數(shù)指定了一個(gè)變量來(lái)保存選項(xiàng)值并提供給腳本使用。如果用戶沒(méi)有提供選項(xiàng),通過(guò)參數(shù)default=False可以設(shè)置默認(rèn)值為False。最后一個(gè)參數(shù)是腳本展示關(guān)于這個(gè)選項(xiàng)的幫助信息。最后,使用parse_args()方法處理參數(shù):args=parser.parse_args()。一旦處理完畢,使用args.option_dest可以獲取到用戶提供的選項(xiàng)值,這里的option_dest就是你設(shè)置參數(shù)時(shí)指定的dest變量。這行代碼getusers(args.no_system)使用用戶提供的no_system選項(xiàng)值作為參數(shù)調(diào)用了getusers()。

接下來(lái)的腳本展示了你該如何在你的腳本里提供用戶一個(gè)非布爾值的選項(xiàng)。這個(gè)腳本重寫了代碼清單6,添加了額外的選項(xiàng)讓你能夠指定檢測(cè)你感興趣的網(wǎng)絡(luò)設(shè)備。

#!/usr/bin/env python
from __future__ import print_function
from collections import namedtuple
import argparse
 
def netdevs(iface=None):
  ''' RX and TX bytes for each of the network devices '''
 
  with open('/proc/net/dev') as f:
    net_dump = f.readlines()
 
  device_data={}
  data = namedtuple('data',['rx','tx'])
  for line in net_dump[2:]:
    line = line.split(':')
    if not iface:
      if line[0].strip() != 'lo':
        device_data[line[0].strip()] = data(float(line[1].split()[0])/(1024.0*1024.0),
                          float(line[1].split()[8])/(1024.0*1024.0))
    else:
      if line[0].strip() == iface:
        device_data[line[0].strip()] = data(float(line[1].split()[0])/(1024.0*1024.0),
                          float(line[1].split()[8])/(1024.0*1024.0))  
  return device_data
 
if __name__=='__main__':
 
  parser = argparse.ArgumentParser(description='Network Interface Usage Monitor')
  parser.add_argument('-i','--interface', dest='iface',
            help='Network interface')
 
  args = parser.parse_args()
 
  netdevs = netdevs(iface = args.iface)
  for dev in netdevs.keys():
    print('{0}: {1} MiB {2} MiB'.format(dev, netdevs[dev].rx, netdevs[dev].tx))

當(dāng)你不提供任何參數(shù)運(yùn)行這個(gè)腳本時(shí),它的運(yùn)行結(jié)果實(shí)際上和之前的版本一樣。但是,你同樣可以指定你可能感興趣的網(wǎng)絡(luò)設(shè)備。舉個(gè)例子:
 

$ ./net_devs_2.py
 
em1: 0.0 MiB 0.0 MiB
wlan0: 146.099492073 MiB 12.9737148285 MiB
virbr1: 0.0 MiB 0.0 MiB
virbr1-nic: 0.0 MiB 0.0 MiB
 
$ ./net_devs_2.py --help
usage: net_devs_2.py [-h] [-i IFACE]
 
Network Interface Usage Monitor
 
optional arguments:
 -h, --help      show this help message and exit
 -i IFACE, --interface IFACE
            Network interface
 
$ ./net_devs_2.py -i wlan0
wlan0: 146.100307465 MiB 12.9777050018 MiB

使你的腳本能在任意地方運(yùn)行

在這篇文章的幫助下,你可能已經(jīng)能夠給自己寫一個(gè)或者更多的有用腳本,這些腳本你想每天都使用,就像Linux的其他命令一樣。去實(shí)現(xiàn)這個(gè)愿望最簡(jiǎn)單的方式就是使這些腳本能夠運(yùn)行(給腳本添加運(yùn)行權(quán)限,譯者注)并且給這些命令設(shè)置BASH別名(BASH alias)。你同樣可以刪除.py后綴并且把這個(gè)文件放到一個(gè)標(biāo)準(zhǔn)位置比如/usr/local/sbin。

其他的有用標(biāo)準(zhǔn)庫(kù)模塊

除了到目前為止我們?cè)谶@篇文章里看到過(guò)的標(biāo)準(zhǔn)庫(kù)外,這里還有很多其它可能有用的標(biāo)準(zhǔn)庫(kù):subprocess,ConfigParser, readline 和 curses。

下一步?

在這個(gè)階段,根據(jù)你自己的Python經(jīng)驗(yàn)和深入探索Linux,你選擇以下方式的一種。如果你已經(jīng)寫了大量的shell腳本或者命令管道去深入探索各種Linux,請(qǐng)?jiān)囈幌翽ython。如果你想以一種更簡(jiǎn)易的方式去寫你自己的腳本工具去執(zhí)行各種任務(wù),請(qǐng)?jiān)囈幌翽ython。最后,如果你已經(jīng)使用其他種類的Python在Linux上編程,祝你使用Python深入探索Linux愉快。

相關(guān)文章

最新評(píng)論