使用 Python 获取 Linux 系统信息
来源:互联网 发布:淘宝宠物疫苗曝光 编辑:程序博客网 时间:2024/04/28 09:02
在本文中,我们将会探索使用Python编程语言工具来检索Linux系统各种信息。走你。
哪个Python版本?
当我提及Python,所指的就是CPython 2(准确的是2.7).我会显式提醒那些相同的代码在CPython 3 (3.3)上是不工作的,以及提供一份解释不同之处的备选代码。请确保你已经安装了CPython,在终端上输入python或者python3回车,然后你在终端上应该能看到python的提示符(prompt)。
请注意,所有的程序在它们第一行都是#!/usr/bin/env/python,也就是说,我们想要Python的解释器来执行这些脚本。因此,如果你想你的脚本具有执行性,请使用chmod +x your-script.py, 那么你就可以使用./your-script.py来执行它了(在本文中你将会看到这种方式)
Lesus
翻译于 4天前
0人顶
顶 翻译的不错哦!
探索platform模块
platform模块在标准库中,它有很多运行我们获得众多系统信息的函数。让我们运行Python解释器来探索它们中的一些函数,那就从platform.uname()函数开始吧:
1
>>>
import
platform
2
>>> platform.uname()
3
(
'Linux'
,
'fedora.echorand'
,
'3.7.4-204.fc18.x86_64'
,
'#1 SMP Wed Jan 23 16:44:29 UTC 2013'
,
'x86_64'
)
如果你已知道linux上的uname命令,那么你就会认出来这个函数就是这个命令的一个接口。在Python 2上,它会返回一个包含系统类型(或者内核版本),主机名,版本,发布版本,机器的硬件以及处理器信息元组(tuple)。你可以使用下标访问个别属性,像这样:
1
>>> platform.uname()[
0
]
2
'Linux'
在Python 3上,这个函数返回的是一个命名元组:
1
>>> platform.uname()
2
3
uname_result(system
=
'Linux'
, node
=
'fedora.echorand'
,
4
release
=
'3.7.4-204.fc18.x86_64'
, version
=
'
#1 SMP Wed Jan 23 16:44:29
5
UTC
2013
', machine='
x86_64
', processor='
x86_64')
Lesus
翻译于 4天前
0人顶
顶 翻译的不错哦!
1
>>> platform.uname().system
2
'Linux'
platform模块还有一些上面属性的直接接口,像这样:
1
>>> platform.system()
2
'Linux'
3
4
>>> platform.release()
5
'3.7.4-204.fc18.x86_64'
linux_distribution()函数返回的有关你所在的linux发布版本的详细信息。例如,在Fedora 18系统上,这个命令会返回如下信息:
1
>>> platform.linux_distribution()
2
(
'Fedora'
,
'18'
,
'Spherical Cow'
)
这个返回结果中包含了版本发布名,版本以及代号元组。特定的Python版本支持的发布版本上可以通过_supported_dists显示的值获得。
1
>>> platform._supported_dists
2
(
'SuSE'
,
'debian'
,
'fedora'
,
'redhat'
,
'centos'
,
'mandrake'
,
3
'mandriva'
,
'rocks'
,
'slackware'
,
'yellowdog'
,
'gentoo'
,
4
'UnitedLinux'
,
'turbolinux'
)
如果你的linux发布版本不在其中(或者其中之一的衍生发行版)。那么你很可能调用了上面这个函数而看不到任何有用的信息。
Lesus
翻译于 4天前
0人顶
顶 翻译的不错哦!
platform模块的最后一个函数,我们将会看看architecture()函数。当你无参的调用这个函数,它会返回包含架构位数以及python可执行的格式的元组,像这样:
1
>>> platform.architecture()
2
(
'64bit'
,
'ELF'
)
在32位的系统上,你将会看到:
1
>>> platform.architecture()
2
(
'32bit'
,
'ELF'
)
如果你指定了系统上其他任何可执行的,你都将会获得相似的结果,如同这样:
1
>>> platform.architecture(executable
=
'/usr/bin/ls'
)
2
(
'64bit'
,
'ELF'
)
鼓励探索platform模块的除了这些的其它函数,找出你现在运行的Python版本。如果你想知道这个模块是如何获取这些信息的,你可以深入查看PYthon源码目录下的Lib/platform.py文件。
os和sys模块也可以获得一些系统属性,例如原生的字节序。接下来,我们超越Python标准库模块,去探索一些在linux系统通过proc和sysfs文件系统使之访问信息成为可能。注意的是通过文件系统来访问信息将会在不同的硬件架构有所不同。所以在读本文或是写脚本时要时刻记住可以试图从这些文件获取信息。
Lesus
翻译于 4天前
0人顶
顶 翻译的不错哦!
CPU信息
/proc/cpuinfo文件包含了你的系统处理器单元的信息。例如,这里就是python版的linux命令cat /proc/cpuinfo所做的事:
01
#! /usr/bin/env python
02
""" print out the /proc/cpuinfo
03
file
04
"""
05
06
from
__future__
import
print_function
07
08
with
open
(
'/proc/cpuinfo'
) as f:
09
for
line
in
f:
10
print
(line.rstrip(
'\n'
))
在下面的代码里列举了使用startwith()字符串方法来显示你的处理器单元的模式。
01
#! /usr/bin/env python
02
03
""" Print the model of your
04
processing units
05
06
"""
07
08
from
__future__
import
print_function
09
10
with
open
(
'/proc/cpuinfo'
) as f:
11
for
line
in
f:
12
# Ignore the blank line separating the information between
13
# details about two processing units
14
if
line.strip():
15
if
line.rstrip(
'\n'
).startswith(
'model name'
):
16
model_name
=
line.rstrip(
'\n'
).split(
':'
)[
1
]
17
print
(model_name)
1
Intel(R) Core(TM) i7
-
3520M
CPU @
2.90GHz
2
Intel(R) Core(TM) i7
-
3520M
CPU @
2.90GHz
3
Intel(R) Core(TM) i7
-
3520M
CPU @
2.90GHz
4
Intel(R) Core(TM) i7
-
3520M
CPU @
2.90GHz
Lesus
翻译于 4天前
0人顶
顶 翻译的不错哦!
01
#! /usr/bin/env python
02
03
""" Find the real bit architecture
04
"""
05
06
from
__future__
import
print_function
07
08
with
open
(
'/proc/cpuinfo'
) as f:
09
for
line
in
f:
10
# Ignore the blank line separating the information between
11
# details about two processing units
12
if
line.strip():
13
if
line.rstrip(
'\n'
).startswith(
'flags'
) \
14
or
line.rstrip(
'\n'
).startswith(
'Features'
):
15
if
'lm'
in
line.rstrip(
'\n'
).split():
16
print
(
'64-bit'
)
17
else
:
18
print
(
'32-bit'
)
Lesus
翻译于 4天前
0人顶
顶 翻译的不错哦!
Lesus
翻译于 4天前
0人顶
顶 翻译的不错哦!
01
#!/usr/bin/env/ python
02
03
"""
04
/proc/cpuinfo as a Python dict
05
"""
06
from
__future__
import
print_function
07
from
collections
import
OrderedDict
08
import
pprint
09
10
def
cpuinfo():
11
''' Return the information in /proc/cpuinfo
12
as a dictionary in the following format:
13
cpu_info['proc0']={...}
14
cpu_info['proc1']={...}
15
16
'''
17
18
cpuinfo
=
OrderedDict()
19
procinfo
=
OrderedDict()
20
21
nprocs
=
0
22
with
open
(
'/proc/cpuinfo'
) as f:
23
for
line
in
f:
24
if
not
line.strip():
25
# end of one processor
26
cpuinfo[
'proc%s'
%
nprocs]
=
procinfo
27
nprocs
=
nprocs
+
1
28
# Reset
29
procinfo
=
OrderedDict()
30
else
:
31
if
len
(line.split(
':'
))
=
=
2
:
32
procinfo[line.split(
':'
)[
0
].strip()]
=
line.split(
':'
)[
1
].strip()
33
else
:
34
procinfo[line.split(
':'
)[
0
].strip()]
=
''
35
36
return
cpuinfo
37
38
if
__name__
=
=
'__main__'
:
39
cpuinfo
=
cpuinfo()
40
for
processor
in
cpuinfo.keys():
41
print
(cpuinfo[processor][
'model name'
])
1
Intel(R) Core(TM) i7
-
3520M
CPU @
2.90GHz
2
Intel(R) Core(TM) i7
-
3520M
CPU @
2.90GHz
3
Intel(R) Core(TM) i7
-
3520M
CPU @
2.90GHz
4
Intel(R) Core(TM) i7
-
3520M
CPU @
2.90GHz
Lesus
翻译于 4天前
0人顶
顶 翻译的不错哦!
内存信息
和/proc/cpuinfo相似,文件/proc/meminfo包含了你电脑的主存的信息。下面的这个程序创建了一个使用这个文件的内容填充的字典。
01
#!/usr/bin/env python
02
03
from
__future__
import
print_function
04
from
collections
import
OrderedDict
05
06
def
meminfo():
07
''' Return the information in /proc/meminfo
08
as a dictionary '''
09
meminfo
=
OrderedDict()
10
11
with
open
(
'/proc/meminfo'
) as f:
12
for
line
in
f:
13
meminfo[line.split(
':'
)[
0
]]
=
line.split(
':'
)[
1
].strip()
14
return
meminfo
15
16
if
__name__
=
=
'__main__'
:
17
#print(meminfo())
18
19
meminfo
=
meminfo()
20
print
(
'Total memory: {0}'
.
format
(meminfo[
'MemTotal'
]))
21
print
(
'Free memory: {0}'
.
format
(meminfo[
'MemFree'
]))
1
Total memory:
7897012
kB
2
Free memory:
249508
kB
Lesus
翻译于 4天前
0人顶
顶 翻译的不错哦!
网络统计信息
接下来,我们会探索我们电脑系统的网络设备。我们将会获得系统的网络接口,以及当系统重启之后通过它们数据发送和接受数据的信息。 /proc/net/dev文件让这些信息可用。如果你检查了这个文件的内容,你就会注意到头一两行包含了头信息等等,这个文件第一列是网络接口名,第二和第三列显示了接收和发送的字节数信息(例如总发送字节数,包数,错误等等)。这里我们所感兴趣的就是他哦难过不同的网络设备提取出总发送数据和接收数据。下面的代码展示了怎么从/proc/net/dev文件中提取出这些信息。
01
#!/usr/bin/env python
02
from
__future__
import
print_function
03
from
collections
import
namedtuple
04
05
def
netdevs():
06
''' RX and TX bytes for each of the network devices '''
07
08
with
open
(
'/proc/net/dev'
) as f:
09
net_dump
=
f.readlines()
10
11
device_data
=
{}
12
data
=
namedtuple(
'data'
,[
'rx'
,
'tx'
])
13
for
line
in
net_dump[
2
:]:
14
line
=
line.split(
':'
)
15
if
line[
0
].strip() !
=
'lo'
:
16
device_data[line[
0
].strip()]
=
data(
float
(line[
1
].split()[
0
])
/
(
1024.0
*
1024.0
),
17
float
(line[
1
].split()[
8
])
/
(
1024.0
*
1024.0
))
18
19
return
device_data
20
21
if
__name__
=
=
'__main__'
:
22
23
netdevs
=
netdevs()
24
for
dev
in
netdevs.keys():
25
print
(
'{0}: {1} MiB {2} MiB'
.
format
(dev, netdevs[dev].rx, netdevs[dev].tx))<span style
=
"font-family:'sans serif', tahoma, verdana, helvetica;font-size:10pt;line-height:1.5;"
> <
/
span>
1
em1:
0.0
MiB
0.0
MiB
2
wlan0:
2651.40951061
MiB
183.173976898
MiB
你可以使用持久的数据存储机制来连接,来写出自己的数据使用监控程序。
Lesus
翻译于 4天前
0人顶
顶 翻译的不错哦!
进程信息
/proc目录包含了所有正运行的进程目录。这些目录的名字和进程的标识符是一样的。所以,如果你遍历/proc目录下那些使用数字作为它们的名字的目录,你就会获得所有现在正在运行的进程列表。在下面的代码中process_list()函数返回所有现在正在运行的进程的标识符列表。当你执行这个程序后,这个列表的长度就是在系统上运行的总进程数。
01
#!/usr/bin/env python
02
"""
03
List of all process IDs currently active
04
"""
05
06
from
__future__
import
print_function
07
import
os
08
def
process_list():
09
10
pids
=
[]
11
for
subdir
in
os.listdir(
'/proc'
):
12
if
subdir.isdigit():
13
pids.append(subdir)
14
15
return
pids
16
17
18
if
__name__
=
=
'__main__'
:
19
20
pids
=
process_list()
21
print
(
'Total number of running processes:: {0}'
.
format
(
len
(pids)))
1
Total number of running processes::
229
每个进程目录包含了一些其他文件和目录,如进程命令的调用,它正使用的共享库以及其它的。
Lesus
翻译于 4天前
0人顶
顶 翻译的不错哦!
块设备
下一个程序通过读sysfs虚拟文件系统列出所有块设备。你系统中的块设备可以从/sys/block目录中找到。因此可能会有/sys/block/sda、/sys/block/sdb等这样的目录。为了获取所有这些设备,我们使用正则表达式对/sys/block目录进行扫描提取感兴趣的块设备。
01
#!/usr/bin/env python
02
03
"""
04
Read block device data from sysfs
05
"""
06
07
from
__future__
import
print_function
08
import
glob
09
import
re
10
import
os
11
12
# Add any other device pattern to read from
13
dev_pattern
=
[
'sd.*'
,
'mmcblk*'
]
14
15
def
size(device):
16
nr_sectors
=
open
(device
+
'/size'
).read().rstrip(
'\n'
)
17
sect_size
=
open
(device
+
'/queue/hw_sector_size'
).read().rstrip(
'\n'
)
18
19
# The sect_size is in bytes, so we convert it to GiB and then send it back
20
return
(
float
(nr_sectors)
*
float
(sect_size))
/
(
1024.0
*
1024.0
*
1024.0
)
21
22
def
detect_devs():
23
for
device
in
glob.glob(
'/sys/block/*'
):
24
for
pattern
in
dev_pattern:
25
if
re.
compile
(pattern).match(os.path.basename(device)):
26
print
(
'Device:: {0}, Size:: {1} GiB'
.
format
(device, size(device)))
27
28
if
__name__
=
=
'__main__'
:
29
detect_devs()
1
Device::
/
sys
/
block
/
sda, Size::
465.761741638
GiB
2
Device::
/
sys
/
block
/
mmcblk0, Size::
3.70703125
GiB
当我运行该程序的时候,有个SD内存卡插在电脑上,因此你会看到程序检测到了它。你也可以扩展该程序识别其它块设备(比如虚拟硬盘)。
袁不语
翻译于 3天前
0人顶
顶 翻译的不错哦!
建立命令行实用工具
linux中命令行使用工具是无所不在的[@Lesus 注:曾有人说过:linux没有了命令行就是个渣。],它允许人么指定命令行参数来定制程序的默认行为。argparse模块就提供了和linux命令行实用工具类似的接口。下面的代码展示了程序如何获得系统上的所有用户以及打印它们的登录shell(使用了pwd标准库模块):
01
#!/usr/bin/env python
02
03
"""
04
Print all the users and their login shells
05
"""
06
07
from
__future__
import
print_function
08
import
pwd
09
10
11
# Get the users from /etc/passwd
12
def
getusers():
13
users
=
pwd.getpwall()
14
for
user
in
users:
15
print
(
'{0}:{1}'
.
format
(user.pw_name, user.pw_shell))
16
17
if
__name__
=
=
'__main__'
:
18
getusers()
现在,你想要程序的用户能够选择是否想看系统用户(像daemon, apache)。我们扩展前面的代码,第一次使用argparse模块来实现这个特性,如下。
01
#!/usr/bin/env python
02
03
"""
04
Utility to play around with users and passwords on a Linux system
05
"""
06
07
from
__future__
import
print_function
08
import
pwd
09
import
argparse
10
import
os
11
12
def
read_login_defs():
13
14
uid_min
=
None
15
uid_max
=
None
16
17
if
os.path.exists(
'/etc/login.defs'
):
18
with
open
(
'/etc/login.defs'
) as f:
19
login_data
=
f.readlines()
20
21
for
line
in
login_data:
22
if
line.startswith(
'UID_MIN'
):
23
uid_min
=
int
(line.split()[
1
].strip())
24
25
if
line.startswith(
'UID_MAX'
):
26
uid_max
=
int
(line.split()[
1
].strip())
27
28
return
uid_min, uid_max
29
30
# Get the users from /etc/passwd
31
def
getusers(no_system
=
False
):
32
33
uid_min, uid_max
=
read_login_defs()
34
35
if
uid_min
is
None
:
36
uid_min
=
1000
37
if
uid_max
is
None
:
38
uid_max
=
60000
39
40
users
=
pwd.getpwall()
41
for
user
in
users:
42
if
no_system:
43
if
user.pw_uid >
=
uid_min
and
user.pw_uid <
=
uid_max:
44
print
(
'{0}:{1}'
.
format
(user.pw_name, user.pw_shell))
45
else
:
46
print
(
'{0}:{1}'
.
format
(user.pw_name, user.pw_shell))
47
48
if
__name__
=
=
'__main__'
:
49
50
parser
=
argparse.ArgumentParser(description
=
'User/Password Utility'
)
51
52
parser.add_argument(
'--no-system'
, action
=
'store_true'
,dest
=
'no_system'
,
53
default
=
False
,
help
=
'Specify to omit system users'
)
54
55
args
=
parser.parse_args()
56
getusers(args.no_system)
1
$ .
/
getusers.py
-
-
help
2
usage: getusers.py [
-
h] [
-
-
no
-
system]
3
4
User
/
Password Utility
5
6
optional arguments:
7
-
h,
-
-
help
show this
help
message
and
exit
8
-
-
no
-
system Specify to omit system users
上面程序使用的一个例子,如下所示:
1
$ ./getusers.py --no-system
2
gene:/bin/
bash
当你传入一个非法的参数,这个程序就会发牢骚(报错)
1
$ ./getusers.py --param
2
usage: getusers.py [-h] [--no-system]
3
getusers.py: error: unrecognized arguments: --param
在上面的程序中,我们简单的理解了如何使用argparse模块。parser = argparse.ArgumentParser(description="User/Password Utility")语句创建了一个带说明程序是做什么的可选描述的ArgumentParser对象,
Lesus
翻译于 3天前
0人顶
顶 翻译的不错哦!
然后,我们添加参数。我们想要程序能够识别接下来这条语句 add_argument()。parser.add_argument('--no-system',action='store_true', dest='no_system', default = False, help='Specify to omit system users')。第一个方法的参数是当系统调用这个程序,程序使用着将要提供这个参数的名称,接下来的参数acton=store_true表明它是一个布尔选择。那就是说,它真或假影响程序的某些行为。dest为可定制化参数,它的值可以提供给程序使用。假如这个值用户不提供,这个值默认false。最后的参数程序显示的帮助信息。最后,参数被解析通过args=parser.parse_args()方法。一旦解析方法被做,用户选项的值能够被抓取到通过相应的语法参数option_dest,当你配置参数的时候,option_dest是一个你指定的目的变量。getusers(args.no_system)这条语句使用用户提供参数的值将会回调getusers()方法。
skyim
翻译于 昨天(11:55)
0人顶
顶 翻译的不错哦!
下面的程序展示了如何指定非布尔类型的选项。该程序是对第6个程序的重写,附加了一个选项用于指定你感兴趣的网络设备。
01
#!/usr/bin/env python
02
from
__future__
import
print_function
03
from
collections
import
namedtuple
04
import
argparse
05
06
def
netdevs(iface
=
None
):
07
''' RX and TX bytes for each of the network devices '''
08
09
with
open
(
'/proc/net/dev'
) as f:
10
net_dump
=
f.readlines()
11
12
device_data
=
{}
13
data
=
namedtuple(
'data'
,[
'rx'
,
'tx'
])
14
for
line
in
net_dump[
2
:]:
15
line
=
line.split(
':'
)
16
if
not
iface:
17
if
line[
0
].strip() !
=
'lo'
:
18
device_data[line[
0
].strip()]
=
data(
float
(line[
1
].split()[
0
])
/
(
1024.0
*
1024.0
),
19
float
(line[
1
].split()[
8
])
/
(
1024.0
*
1024.0
))
20
else
:
21
if
line[
0
].strip()
=
=
iface:
22
device_data[line[
0
].strip()]
=
data(
float
(line[
1
].split()[
0
])
/
(
1024.0
*
1024.0
),
23
float
(line[
1
].split()[
8
])
/
(
1024.0
*
1024.0
))
24
return
device_data
25
26
if
__name__
=
=
'__main__'
:
27
28
parser
=
argparse.ArgumentParser(description
=
'Network Interface Usage Monitor'
)
29
parser.add_argument(
'-i'
,
'--interface'
, dest
=
'iface'
,
30
help
=
'Network interface'
)
31
32
args
=
parser.parse_args()
33
34
netdevs
=
netdevs(iface
=
args.iface)
35
for
dev
in
netdevs.keys():
36
print
(
'{0}: {1} MiB {2} MiB'
.
format
(dev, netdevs[dev].rx, netdevs[dev].tx))
01
$ ./net_devs_2.py
02
03
em1: 0.0 MiB 0.0 MiB
04
wlan0: 146.099492073 MiB 12.9737148285 MiB
05
virbr1: 0.0 MiB 0.0 MiB
06
virbr1-nic: 0.0 MiB 0.0 MiB
07
08
$ ./net_devs_2.py --help
09
usage: net_devs_2.py [-h] [-i IFACE]
10
11
Network Interface Usage Monitor
12
13
optional arguments:
14
-h, --help show this help message and
exit
15
-i IFACE, --interface IFACE
16
Network interface
17
18
$ ./net_devs_2.py -i wlan0
19
wlan0: 146.100307465 MiB 12.9777050018 MiB
袁不语
翻译于 3天前
0人顶
顶 翻译的不错哦!
脚本的系统范围可用性
在本文的帮助下,你可能已经可以写一个或多个有用的脚本,就像其它linux命令一样,你想要每天都使用它们。最简单的方式是将脚本设置为可执行的,然后为脚本设置一个BASH别名。你也可以移除.py扩展名,然后将脚本放在诸如/usr/local/sbin这样的标准位置。
其它有用的标准库模组
除了本文中已经提到的标准库模组,还有很多其它有用的标准模组:subprocess、ConfigParser、readline和curses。
袁不语
翻译于 3天前
0人顶
顶 翻译的不错哦!
接下来做什么?
在这个阶段,依靠你自己使用Python的经验,探索Linux内部,你可以参考下面的任一方式。如果你曾经需要写很多shell脚本/命令流水线来探索Linux内部,那么试一下Python。如果你想要一个更简单的方式来编写执行很多任务的实用程序脚本,那么试一下Python。最后,如果你已经使用Python在Linux上别写其它目的的程序,那么试一下用Python探索Linux内部。
资源
Python资源
- Lists
- Tuples
- Namedtuples
- OrderedDict
- split()
- strip() rstrip() and other string methods
- Reading and writing files
- os module
- platform module
- pwd module
- spwd module
- grp module
- subprocess module
- ConfigParser module
- readline module
系统信息
- Long Mode
- /proc file system
- sysfs
- 使用 Python 获取 Linux 系统信息
- 使用 Python 获取 Linux 系统信息
- 使用 Python 获取 Linux 系统信息
- 使用 Python 获取 Linux 系统信息
- 使用 Python 获取 Linux 系统信息
- linux系统使用python获取内存使用信息
- 使用python获取CPU和内存信息(linux系统)
- 使用Python获取Linux系统的各种信息
- 使用 Python 获取 Linux 系统信息的代码
- 使用Python获取Linux系统的各种信息
- 使用Python收集获取Linux系统主机信息
- python获取linux的系统信息
- python获取linux的系统信息
- Python脚本获取Linux系统信息
- python中系统信息获取psutil使用
- 使用python获取系统网络信息
- 运用Python语言编写获取Linux基本系统信息(二):文件系统使用情况获取
- python获取系统信息
- 根据文本关键字寻找文件(看哪些文件包含某某字符串)
- 关于C++中const的一些总结
- 如何查杀僵尸进程
- UIAlertView备忘
- hdu 1019 Least Common Multiple
- 使用 Python 获取 Linux 系统信息
- 运行地址
- oracle的dbms_scheduler
- 内存管理2对象之间的内存管理
- (13)拨云见日,闲聊哈希表
- Linux新手入门之如何登入登出Linux操作系统
- 设计模式之适配器模式(Adapter)
- 完全删除SQL server 2008
- POJ 3009 Curling 2.0