用Python制作檢測(cè)Linux運(yùn)行信息的工具的教程
在這篇文章里,我們將會(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)文章
python 實(shí)現(xiàn)將多條曲線畫在一幅圖上的方法
今天小編就為大家分享一篇python 實(shí)現(xiàn)將多條曲線畫在一幅圖上的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-07-07關(guān)于不懂Chromedriver如何配置環(huán)境變量問(wèn)題解決方法
這篇文章主要介紹了關(guān)于不懂Chromedriver如何配置環(huán)境變量問(wèn)題解決方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-06-06pyspark連接mysql數(shù)據(jù)庫(kù)報(bào)錯(cuò)的解決
本文主要介紹了pyspark連接mysql數(shù)據(jù)庫(kù)報(bào)錯(cuò)的解決,因?yàn)閟park中缺少連接MySQL的驅(qū)動(dòng)程序,下面就來(lái)介紹一下解決方法,感興趣的可以了解一下2023-11-11從0到1使用python開(kāi)發(fā)一個(gè)半自動(dòng)答題小程序的實(shí)現(xiàn)
這篇文章主要介紹了從0到1使用python開(kāi)發(fā)一個(gè)半自動(dòng)答題小程序的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05python實(shí)現(xiàn)學(xué)生信息管理系統(tǒng)(精簡(jiǎn)版)
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)學(xué)生信息管理系統(tǒng)的精簡(jiǎn)版,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11python對(duì)列進(jìn)行平移變換的方法(shift)
今天小編就為大家分享一篇python對(duì)列進(jìn)行平移變換的方法(shift),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-01-01Python編程functools模塊創(chuàng)建修改的高階函數(shù)解析
本篇文章主要為大家介紹functools模塊中用于創(chuàng)建、修改函數(shù)的高階函數(shù),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2021-09-09