linux /proc 文件解析

费了两个晚上终于看懂了。  友情提醒。 文章中的例子要想在linux跑通需要手工把&&连接的语句放到一行。

Linux procfs详解 
1.0 proc文件系统总览 
在类Unix系统中体现了一种良好的抽象哲学,就是几乎所有的数据实体都被抽象成一个统一的接口--文件来看待,这样我们就可以用一些简单的基本工具完成大量复杂的操作。在Linux中存在着一类 
特殊的伪文件系统,用于使用与文件接口统一的操作来完成各种功能,例如ptyfs、devfs、sysfs和procfs。而procfs就是其中应用最广泛的一种伪文件系统。 
procfs是Linux内核信息的抽象文件接口,大量内核中的信息以及可调参数都被作为常规文件映射到一个目录树中,这样我们就可以简单直接的通过echo或cat这样的文件操作命令对系统信息进行查取 
和调整了。同时procfs也提供了一个接口,使得我们自己的内核模块或用户态程序可以通过procfs进行参数的传递。在当今的Linux系统中,大量的系统工具也通过procfs获取内核参数,例如ps、 
lspci等等,没有procfs它们将可能不能正常工作。 
procfs的使用如同常规的文件系统一样,例如加载一个procfs (首先确定你的内核已经支持procfs默认如此): 
# mount -t proc none /proc 
也可以在/etc/fstab中加入如下一行使系统在启动时自动加载procfs(大多数系统中也是默认如此): 
none /proc proc defaults 0 0 
在proc文件系统中,主要包含三大类内容,进程相关部分,系统信息部分,以及系统子系统部分。在下面我们可以看到一个典型的procfs布局: 
> ls /proc 
1 2 2166 2281 cmdline interrupts meminfo stat 
13 2001 2167 3 cpuinfo iomem misc swaps 
1646 2042 2168 4 crypto ioports modules sys 
1780 2058 2169 5 devices irq mounts sysrq-trigger 
1834 2087 2170 6 dma isapnp mtrr sysvipc 
1838 2096 2171 7 driver kcore net tty 
1857 2107 2207 71 execdomains kmsg partitions uptime 
1877 2117 2208 8 fb ksyms pci version 
1889 2143 2216 9 filesystems loadavg scsi 
1905 2153 2217 apm fs locks self 
1960 2165 2219 bus ide mdstat slabinfo 
在上面的布局中我们可以看到procfs包含的内容: 
* 进程相关部分 (只读) 
这部分文件都是以数字为名的子目录,这个数字就是相关进程的进程ID,在 1.1节中会详细介绍进程相关子目录的结构和信息。 
需要注意的是procfs中进程子系统部分的一个特殊点,就是/proc/self,它是指向当前执行进程的符号连接,或者说--是指向未来你将要执行指令的心灵感应: 
> cat self/cmdline 
catself/cmdline 
在这个命令中,我们希望它显示当前进程的cmdline参数,它恰恰就显示了当前进程--我们所执行的这条命令,cat self/cmdline。幸好这条指令显示出的信息会忽略空格,导致显示略微的不正常,否则我们倒是可以很容易的使用`cat self/cmdline`这样的命令制造出永远循环执行的进程来。;> 
* 内核信息部分 (只读) 
这部分文件同样处于/proc的顶层目录,不过它们大部分都是常规、只读的文本文件,可以直接用cat查看信息。作为系统内核执行体的抽象,我们也可以把它看作内核"进程"的信息部分,当然虽然并不存在这个进程实体。这里比较特别的一个文件是 /proc/cmdline : 
>cat cmdline 
ro root=/dev/hda2 
在这个文件中存放的是系统内核引导时的命令行参数。此部分内容将在 1.3节中说明。 
* 内核各子系统相关部分 (部分可调) 
这部分是系统内核参数调整的重头戏,在procfs中,除去上面所述的两部分内容外,还有很大一部分信息文件被存放在了一些并非以数字命名的特殊目录中,这些目录下的信息就是内核各个重要子系统的信息和可调参数,主要有: 
bus 总线信息(只读) 
drivers 驱动信息(只读) 
fs 文件系统特别信息(只读) 
ide IDE接口信息(只读) 
irq IRQ信息(只读) 
net 网络子系统信息(只读) 
scsi SCSI系统信息(只读) 
sysvipc IPC子系统信息(只读) 
tty tty子系统信息(只读) 
sys 系统内核可调参数 (可调) 
作为Linux系统内核参数的抽象文件接口,Linux内核的大部分默认可调参数都被放在了 /proc/sys目录下,这些参数都以常规文件的形式体现,并且可以用echo/cat等文件操作命令进行调整,调整的效果是即时的,并且在系统运行的整个生命周期之间都有效(知道再次改变它们或者系统重启)。 
当然Linux也提供了另外一种途径sysctl来调整这些参数,sysctl是从BSD系统继承而来的一种系统参数动态调整方法,sysctl的使用更为简单,并且可以使用/etc/sysctl.conf保存配置以在下次启动时自动加载这些设置。对于sysctl可调参数体积调整方法将在另一篇文章中说明。 
对于内核信息和参数的说明将在 1.4 - 1.7节中解释;对于/proc/sys中的可调参数将在第二章中详细说明。 
1.1 进程相关子目录 
在/proc目录中包含了一些以数字为名的子目录,这些目录就是系统当前运行进程的proc抽象。每一个目录都以相关联的活动系统进程PID为目录名,在目录下包含了一些文件,用于显示进程相关的信息。每个进程映射子目录的结构都如 Table 1-1. 
.............................................................................. 
文件名 内容 
cmdline 执行进程的命令行参数 
cpu 在SMP系统中近程最后的执行CPU (2.4)(smp) 
cwd 到当前工作目录的符号链接 
environ 环境变量 
exe 链接到进程对应的源可执行文件 
fd 包含所有进程打开的文件描述符的子目录 
maps 进程内存映射,包含进程执行空间以及动态链接库信息 (2.4) 
mem 进程内存空间 
root 连接到进程执行时的 / (root)目录 
stat 进程状态 
statm 进程内存状态信息 
status 进程状态总览,包含进程名字、当前状态和各种信息统计 
.............................................................................. 
举例来说,要获取一个进程的状态,只要读取下面进程PID子目录下的status文件 /proc/PID/status: 
>cat /proc/self/status 
Name: cat 
State: R (running) 
Pid: 5452 
PPid: 743 
TracerPid: 0 (2.4) 
Uid: 501 501 501 501 
Gid: 100 100 100 100 
Groups: 100 14 16 
VmSize: 1112 kB 
VmLck: 0 kB 
VmRSS: 348 kB 
VmData: 24 kB 
VmStk: 12 kB 
VmExe: 8 kB 
VmLib: 1044 kB 
SigPnd: 0000000000000000 
SigBlk: 0000000000000000 
SigIgn: 0000000000000000 
SigCgt: 0000000000000000 
CapInh: 00000000fffffeff 
CapPrm: 0000000000000000 
CapEff: 0000000000000000 
如同第一节所说,/proc/self连接指向读取它自身的进程映像,在之后一节的例子中都将以它作为我们的范例。 
这条命令显示的信息与你通过 /bin/ps 命令获取到的进程信息基本相同,这恰巧是因为,ps也是通过读取procfs来获取这些信息的。statm 文件包含了更详细的进程内存状态,statm的详细内容按照数据项由左向右依次如 Table 1-2. 
> cat /proc/self/statm 
105 105 93 4 12 89 12 
.............................................................................. 
数据项 内容 
size 程序大小 
resident 常驻内存空间大小 
shared 共享内存页数 
trs 代码段占用内存页数 
drs 数据/堆栈段占用内存页数 
lrs 引用库占用内存页数 
dt 脏页数量 
.............................................................................. 
1.2 内核数据 
相似于进程入口,在/proc目录下的其他一些文件给出了内核信息数据,这些文件包含了系统当前运行内核相关信息。/proc目录下内核相关信息文件在Table 1-3 中列出,依赖于您的系统配置和加载的内核模块,在您的系统中的显示可能会略有不同。 
.............................................................................. 
文件 内容 
apm 高级电源管理信息 
bus bus总线相关信息 
cmdline 内核引导命令行参数 
cpuinfo cpu信息 
devices 当前可用设备 (包含所有块设备和字符设备) 
dma DMA通道使用状况 
filesystems 当前内核支持的文件系统 
driver 驱动相关信息 (2.4) 
execdomains 安全相关的Execdomains信息 (2.4) 
fb Frame Buffer 设备 (2.4) 
fs 本地文件系统参数 (2.4) 
ide IDE子系统相关信息的子目录 
interrupts 中断使用状况 
iomem 内存映射图 (2.4) 
ioports I/O端口使用状况 
irq 关联到cpu的irq使用状况 (2.4)(smp?) 
isapnp ISA PnP (即插即用) 信息 (2.4) 
kcore Kernel core image,内核转储映像 (2.4) 
kmsg Kernel messages 
ksyms Kernel symbol table,内核符号表 
loadavg 最后1、5 、15 分钟的平均负载 
locks Kernel locks, 内核锁信息 
meminfo 内存信息 
misc 内核信息杂项 
modules 已加载内核模块列表 
mounts 已加载的文件系统 
net 网络子系统信息 
partitions 已识别的本地系统分区表 
pci PCI总线相关信息,在新版本中指向 /proc/bus/pci/ 目录 (2.4) 
rtc rtc实时钟 
scsi SCSI 总线信息 
slabinfo Slab 内存分配池信息 
stat 内核状态总览 
swaps Swap 空间状态 
sys 内核系统参数 (参见第二章) 
sysvipc SysVIPC 资源状态 (msg, sem, shm) (2.4) 
tty TTY驱动信息 
uptime 系统 uptime 
version 内核版本 
video video 资源状态 (2.4) 
.............................................................................. 
在proc文件系统中大多数文件都是可读的文本,可以直接使用系统中的常规文件处理命令进行操作。当然,这也依赖于目标文件的权限属性。例如要查看系统中断信息 /proc/interrupts: 
> cat /proc/interrupts 
CPU0 
0: 8728810 XT-PIC timer 
1: 895 XT-PIC keyboard 
2: 0 XT-PIC cascade 
3: 531695 XT-PIC aha152x 
4: 2014133 XT-PIC serial 
5: 44401 XT-PIC pcnet_cs 
8: 2 XT-PIC rtc 
11: 8 XT-PIC i82365 
12: 182918 XT-PIC PS/2 Mouse 
13: 1 XT-PIC fpu 
14: 1232265 XT-PIC ide0 
15: 7 XT-PIC ide1 
NMI: 0 
在2.4版内核中,当使用了SMP时这个文件末尾会多出两行SMP相关属性 LOC & ERR : 
> cat /proc/interrupts 
CPU0 CPU1 
0: 1243498 1214548 IO-APIC-edge timer 
1: 8949 8958 IO-APIC-edge keyboard 
2: 0 0 XT-PIC cascade 
5: 11286 10161 IO-APIC-edge soundblaster 
8: 1 0 IO-APIC-edge rtc 
9: 27422 27407 IO-APIC-edge 3c503 
12: 113645 113873 IO-APIC-edge PS/2 Mouse 
13: 0 0 XT-PIC fpu 
14: 22491 24012 IO-APIC-edge ide0 
15: 2183 2415 IO-APIC-edge ide1 
17: 30564 30414 IO-APIC-level eth0 
18: 177 164 IO-APIC-level bttv 
NMI: 2457961 2457959 
LOC: 2457882 2457881 
ERR: 2155 
NMI是每个CPU上产生的不可屏蔽中断(Non Maskable Interrupt)的计数; 
LOC是每个CPU上APIC本地中断的计数。 
ERR是SMP系统中IO-APIC总线失败错误的计数,如果这个数量太高,可能你的内核运行会有问题,这时候就需要测试内核,查看硬件和APIC是否有兼容性问题。 
在2.4内核中irq相关的内核信息被放在/proc/irq目录下,在这个目录下包含一个文件 
prof_cpu_mask和每个IRQ独属的一个子目录。 
> ls /proc/irq/ 
0 10 12 14 16 18 2 4 6 8 prof_cpu_mask 
1 11 13 15 17 19 3 5 7 9 
> ls /proc/irq/0/ 
smp_affinity 
2.4内核中可以使用IRQ绑定属性,是某个或全部的IRQ挂接到SMP集合中的某个CPU上,这个特性可以通过prof_cpu_mask和smp_affinity来调整。在默认情况下这两个文件的内容都"ffffffff",作为一个位映射而存在,你可以使用echo命令来指定一个CPU处理IRQ事件。 
> cat /proc/irq/0/smp_affinity 
ffffffff 
> echo 1 > /proc/irq/prof_cpu_mask 
这天命令的结果就是系统中只有第一个CPU可以捕获IRQ事件,如果您使用的是"echo 5"的话那么第一和第四个CPU都可以捕获和处理事件(1 + 4)。 
在默认情况下IRQ事件由IO-APIC分配,它将轮询每个配置中的CPU,等待其中一个处理事件响应。 
在slabinfo文件文件中我们可以看到Linux内核的内存分配池信息,2.4版本内核中使用slab算法来为内核对象(网络缓存、目录高速缓存以及文件分配表等等)分配内存页。 
在/proc目录下还有三个重要的目录: net,scsi和sys,我们会在后面的章节中陆续描述;此外如果您的系统中没有SCSI设备(或没有SCSI驱动)的话,/proc/scsi目录是不存在的。 
1.3 IDE设备 /proc/ide 
/proc/ide目录下包含了所有内核识别出的IDE设备的信息。在/proc/ide目录下包含drivers文件和若干个以IDE设备名或IDE控制器名为名的子目录。 
> ls -alF /proc/ide/ 
total 3 
dr-xr-xr-x 4 root root 0 10月 9 23:36 ./ 
dr-xr-xr-x 54 root root 0 2004-10-10 ../ 
-r--r--r-- 1 root root 0 10月 9 23:36 drivers 
lrwxrwxrwx 1 root root 8 10月 9 23:36 hda -> ide0/hda/ 
lrwxrwxrwx 1 root root 8 10月 9 23:36 hdb -> ide0/hdb/ 
lrwxrwxrwx 1 root root 8 10月 9 23:36 hdc -> ide1/hdc/ 
dr-xr-xr-x 4 root root 0 10月 9 23:36 ide0/ 
dr-xr-xr-x 3 root root 0 10月 9 23:36 ide1/ 
-r--r--r-- 1 root root 0 10月 9 23:36 piix 
drivers文件包含了当前加载的IDE设备驱动: 
> cat /proc/ide/drivers 
ide-floppy version 0.99.newide 
ide-disk version 1.17 
ide-default version 0.9.newide 
在/proc/ide目录下还可以看到其他一些以设备命名的目录,在这些目录下我们可以看到更详细的信息。piix是IDE控制芯片组的名字,在你的系统中可能是其他名字。此外还包含若干个(一般的PC上是2个)IDE控制器为名的目录,以及以IDE终端设备名命名的快捷方式,它门将链接到控制器目录下对应的设备文件上。 
在ide*目录中我们可以得到更多的信息,如 Table 1-4. 
.............................................................................. 
文件名 内容 
channel IDE通道 (0 or 1) 
config 配置 (only for PCI/IDE bridge) 
mate Mate name 
model IDE控制器的类型/芯片组 
hd? IDE总线上连接的可用设备 
.............................................................................. 
当前连接在控制器上的每个设备也将成为一个单独的子目录,如 Table 1-5. 
.............................................................................. 
文件名 内容 
cache 设备缓存大小 
capacity 设备数据块数量 (按 512Byte 块) 
driver 驱动和版本 
geometry 物理和逻辑的设备参数 
identify 设备标示块 
media 媒体类型 
model 设备标识符(型号或名字) 
settings 设备配置参数 
smart_thresholds IDE disk management thresholds 
smart_values IDE disk management values 
.............................................................................. 
在这里比较有用的信息是settings文件,它包含了一个驱动器相关的信息总览: 
# cat /proc/ide/ide0/hda/settings 
name value min max mode 
---- ----- --- --- ---- 
bios_cyl 526 0 65535 rw 
bios_head 255 0 255 rw 
bios_sect 63 0 63 rw 
breada_readahead 4 0 127 rw 
bswap 0 0 1 r 
file_readahead 72 0 2097151 rw 
io_32bit 0 0 3 rw 
keepsettings 0 0 1 rw 
max_kb_per_request 122 1 127 rw 
multcount 0 0 8 rw 
nice1 1 0 1 rw 
nowerr 0 0 1 rw 
pio_mode write-only 0 255 w 
slow 0 0 1 rw 
unmaskirq 0 0 1 rw 
using_dma 0 0 1 rw 
1.4 网络信息 /proc/net 
/proc/net 子目录包含了系统中网络相关的内核统计信息和视图,常规的文件列表如Table 1-7 中说明; 如果你的内核支持IPV6,那么还有一些IPV6相关信息在 Table 1-6中 
.............................................................................. 
文件名 内容 
udp6 UDP sockets (IPv6) 
tcp6 TCP sockets (IPv6) 
raw6 Raw 设备状态 (IPv6) 
igmp6 系统当前加入的IP多播地址 (IPv6) 
if_inet6 IPv6 网络接口地址列表 
ipv6_route IPv6 内核路由表 
rt6_stats IPv6 全局路由表状态 
sockstat6 Socket 状态 (IPv6) 
snmp6 Snmp 数据 (IPv6) 
.............................................................................. 
.............................................................................. 
文件名 内容 
arp 内核 ARP 表 
atm atm设备接口信息 
drivers 加载的驱动模块信息 
dev 网络设备以及状态 
dev_mcast 二层多播组以及监听设备信息 
(包含interface index, label, number of references, number of 
bound addresses). 
dev_stat 网络设备状态 
ip_fwchains ipchains 防火墙规则链 (2.2) 
ip_fwnames ipchains 防火墙规则链名 (2.2) 
ip_masq 包含IP伪装映射表的目录 (2.2) 
ip_masquerade 主IP伪装映射表 (2.2) 
netstat 网络状态 
raw 原始设备状态 
route 内核路由表 
rpc 包含rpc信息的目录 
rt_cache 路由cache 
snmp SNMP 数据 
sockstat Socket 状态 
tcp TCP sockets 
tr_rif Token ring RIF 令牌环网路由表 
udp UDP sockets 
unix UNIX domain sockets 
wireless Wireless 接口数据 (Wavelan etc) 
igmp 主机当前加入的IP多播组地址 
psched 全局数据包调度参数 
netlink PF_NETLINK sockets 列表 
ip_mr_vifs 多播虚拟地址列表 
ip_mr_cache 多播路由cache列表 
.............................................................................. 
由于2.4之后的内核引入了netfilter/iptables防火墙,因此在防火墙部分的信息与2.2略有不同: 
.............................................................................. 
文件名 内容 
ip_tables_matches iptables支持的过滤模式 
ip_tables_names iptables规则表名字 
ip_tables_targets iptables规则链目标 
ip_conntrack iptables状态检测跟踪表 
.............................................................................. 
您可以使用这些信息来查看当前系统中可用的网络设备,以及这些设备上通过的流量和路由信息: 
> cat /proc/net/dev 
Inter-|Receive |[... 
face |bytes packets errs drop fifo frame compressed multicast|[... 
lo: 908188 5596 0 0 0 0 0 0 [... 
ppp0:15475140 20721 410 0 0 410 0 0 [... 
eth0: 614530 7085 0 0 0 0 0 1 [... 
...] Transmit 
...] bytes packets errs drop fifo colls carrier compressed 
...] 908188 5596 0 0 0 0 0 0 
...] 1375103 17405 0 0 0 0 0 0 
...] 1703981 5535 0 0 0 3 0 0 
如果系统中使用了Ethernet Channel特性,使若干个物理接口绑定为一个逻辑设备的话,这个逻辑设备将会拥有一个以设备名命名的子目录,其中包含一些bond模块相关的特殊信息。例如把eth0和eth1绑定为设备 bond0 ,那么可以在 /proc/net/bond0/目录下看到bond的特殊信息,例如主从接口、链路状态等等。 
1.5 SCSI 设备信息 
如果你的系统中含有任何SCSI设备,那么在 /proc/scsi 目录下可以看到系统识别到的SCSI设备相关信息: 
>cat /proc/scsi/scsi 
Attached devices: 
Host: scsi0 Channel: 00 Id: 00 Lun: 00 
Vendor: IBM Model: DGHS09U Rev: 03E0 
Type: Direct-Access ANSI SCSI revision: 03 
Host: scsi0 Channel: 00 Id: 06 Lun: 00 
Vendor: PIONEER Model: CD-ROM DR-U06S Rev: 1.04 
Type: CD-ROM ANSI SCSI revision: 02 
系统中的SCSI设备将映射到/proc/scsi目录下形成一个子树,按照对应的设备模块和设备总线号可以查看相应设备的参数信息,例如一个Adaptec AHA-2940 SCSI 适配器: 
> cat /proc/scsi/aic7xxx/0 
Adaptec AIC7xxx driver version: 5.1.19/3.2.4 
Compile Options: 
TCQ Enabled By Default : Disabled 
AIC7XXX_PROC_STATS : Disabled 
AIC7XXX_RESET_DELAY : 5 
Adapter Configuration: 
SCSI Adapter: Adaptec AHA-294X Ultra SCSI host adapter 
Ultra Wide Controller 
PCI MMAPed I/O Base: 0xeb001000 
Adapter SEEPROM Config: SEEPROM found and used. 
Adaptec SCSI BIOS: Enabled 
IRQ: 10 
SCBs: Active 0, Max Active 2, 
Allocated 15, HW 16, Page 255 
Interrupts: 160328 
BIOS Control Word: 0x18b6 
Adapter Control Word: 0x005b 
Extended Translation: Enabled 
Disconnect Enable Flags: 0xffff 
Ultra Enable Flags: 0x0001 
Tag Queue Enable Flags: 0x0000 
Ordered Queue Tag Flags: 0x0000 
Default Tag Queue Depth: 8 
Tagged Queue By Device array for aic7xxx host instance 0: 
{255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255} 
Actual queue depth per device for aic7xxx host instance 0: 
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1} 
Statistics: 
(scsi0:0:0:0) 
Device using Wide/Sync transfers at 40.0 MByte/sec, offset 8 
Transinfo settings: current(12/8/1/0), goal(12/8/1/0), user(12/15/1/0) 
Total transfers 160151 (74577 reads and 85574 writes) 
(scsi0:0:6:0) 
Device using Narrow/Sync transfers at 5.0 MByte/sec, offset 15 
Transinfo settings: current(50/15/0/0), goal(50/15/0/0), user(50/15/0/0) 
Total transfers 0 (0 reads and 0 writes) 
1.6 并口信息 /proc/parport 
/proc/parport 包含系统并口信息,按照并口端口号(0,1,2,...)每个设备将映射到一个子目录中。在这个目录下包含的信息如 Table 1-8. 
.............................................................................. 
文件名 内容 
autoprobe IEEE-1284 标准兼容的设备ID信息 
devices 端口使用的设备驱动列表 
hardware 端口使用的base address, IRQ line 和 DMA channel. 
irq 端口使用的IRQ号,你可以写入一个新值指定IRQ号 (IRQ number or none). 
.............................................................................. 
1.7 TTY信息 /proc/tty 
------------------------- 
在/proc/tty目录中包含了系统中当前在用的tty及其信息,在这个目录中也可以找到设备 
信息和线路disciplines,如 Table 1-9. 
Table 1-9: /proc/tty 中的文件 
.............................................................................. 
文件名 内容 
drivers 设备及引用计数 
ldiscs registered line disciplines 
driver/serial tty线路状态 
.............................................................................. 
要查看系统中的当前在用ttys,可以简单的查看 /proc/tty/drivers: 
> cat /proc/tty/drivers 
pty_slave /dev/pts 136 0-255 pty:slave 
pty_master /dev/ptm 128 0-255 pty:master 
pty_slave /dev/ttyp 3 0-255 pty:slave 
pty_master /dev/pty 2 0-255 pty:master 
serial /dev/cua 5 64-67 serial:callout 
serial /dev/ttyS 4 64-67 serial 
/dev/tty0 /dev/tty0 4 0 system:vtmaster 
/dev/ptmx /dev/ptmx 5 2 system 
/dev/console /dev/console 5 1 system:console 
/dev/tty /dev/tty 5 0 system:/dev/tty 
unknown /dev/tty 4 1-63 console 
本章介绍了 /proc 文件系统提供的系统运行时信息. 在 /proc 文件系统中,您不仅可以简单直接的访问进程相关信息,也可以通过它查看各个方面的系统内核状态。 
在 /proc 文件系统中,大部分信息都以常规或文本文件的形式反映出来,您可以任意使用简单的文件处理命令来查看它(只要权限允许);如果某些文件不能被查看或者产生乱码,那么它可能是一些特殊类型的文件,需要其它手段来处理,例如 /proc/kcore 可以通过gdb等内核调试工具来查看,而其他一些数据则可以被ps、top等工具所理解。 
在这一章中,我们对procfs的结构进行了一下纵览,对它的作用也该有一些了解了。在procfs中除了得到大量系统内核信息之外,它最重要的一个作用莫过于对进程的监控和分析了。有了procfs,你也可以写出自己的ps/top来,甚至不用任何编程工具...... 
比如,很多Linux新手都常常遇到的一个问题,就是夹在了一个文件系统之后不能卸载,系统报告这样的错误: 
代码: 
# umount /db1                                            
umount: /db1: device is busy 
经验老到的管理员们都知道,这个问题是由于某些进程的工作目录还在这个目录下,导致系统卷忙而无法卸载,只要杀掉那个进程,文件系统就可以正常卸载了。但究竟是哪个进程还在那里呢?找起来恐怕也要费半天神。虽然有pfile和lsof之类的工具可用,但总 也有应急的时候吧,这棵小脚本就可以为你解忧。 
代码: 
#!/bin/bash 
#pcwd.sh,查找系统中工作在目标路径下的进程,使用方法: pcwd.sh 路径名 
test $1 || { echo "Usage: pcwd.sh path(absolute path)" && exit }; 
PS=`ls /proc/*[0-9]*|grep :` ; 
PSList=`echo $PS |tr -d '/proc'|tr -d ':'`; 
for PID in $PSList 
  do 
  test -e /proc/$PID && (ls -alF /proc/$PID/cwd|grep $1 >/dev/null ) && echo "Process $PID (`cat /proc/$PID/status |grep Name |tr -d 'Name: '`) is work in $1 "; 
done 
就是这样短短的几行代码,甚至不用任何的临时文件,我们就获取了执行命令前的当前系统进程表映像,然后遍历每个进程的proc目录,找到占用我们目录的"坏进程"。 
在我的系统上的输出: 
代码: 
[elly@frost.llnl]/tmp# ./pcwd.sh 
Usage: pcwd.sh path(absolute path) 
[elly@frost.llnl]/tmp# ./pcwd.sh /usr 
Process 1283 (vi) is work in /usr ; 
Process 3113 (bsh) is work in /usr ; 
在上面的例子中,我们只用了最简单的四五个文件和文本处理命令,就完成了这个小程序,你甚至可以把所有的语句写在一行上,通过命令行或alias定义就完成这个功能。 
把它稍稍修改一下就是另外一个功能,查找正在使用某个文件的进程: 
代码: 
#!/bin/bash 
test $1 || { echo "Usage: pfile.sh filename(absolute path)" && exit }; 
PS=`ls /proc/*[0-9]*|grep :` ; 
PSList=`echo $PS |tr -d '/proc'|tr -d ':'`; 
for PID in $PSList 
  do 
  test -e /proc/$PID && (ls -alF /proc/$PID/fd|grep $1 >/dev/null ) && echo "Process $PID (`cat /proc/$PID/status |grep Name |tr -d 'Name: '`) is openning $1;"; 
done 
在我系统上的输出: 
代码: 
[elly@frost.llnl]/tmp# ./pfile.sh 
Usage: pfile.sh filename(absolute path) 
[elly@frost.llnl]/tmp# ./pfile.sh access_log 
Process 109 (httpd) is openning access_log; 
Process 110 (httpd) is openning access_log; 
Process 112 (httpd) is openning access_log; 
Process 113 (httpd) is openning access_log; 
Process 116 (httpd) is openning access_log; 
Process 99 (httpd) is openning access_log; 

目标文件名可以使用相对或绝对路径,甚至可以只输入半个文件名...当然路径越精确查找的结果也越准确。在这个例子中,很容易就可以扩展它的功能,让它实现类似lsof的功能,可以列举系统中所有正在被使用的文件。好啦,我们做一个有用点的程序。 
ps,每台机器上都有吧。不幸的是,在某些极端环境下,系统中的PS是不可靠的,比如,坏了...或被人替换了。 
很多恶意的黑客入侵系统之后会在系统上安装一类叫rootkit的后门包,用来替换系统中ps、netstat等重要程序以隐藏自己的痕迹,这个时候一般比较稳妥的办法是自己上传一份可靠的系统工具包,或者静态编译的工具包。当然,也可以用这个土办法,直 接从procfs里读取信息。(如果是比较高明的黑客,使用LKM等内核后门那这个就没有用了哦) 
范例:懒人的ps,就叫它lps吧。 
代码: 
#!/bin/bash 
PS=`ls /proc/*[0-9]*|grep :` ; 
PSList=`echo $PS |tr -d '/proc' |tr -d ':' |sort `; 
echo -e "PID PPID UID GID STAT  MEM TTY CMD" 
for PID in $PSList 
  do 
  test -e /proc/$PID && sPID=`cat /proc/$PID/status |grep ^Pid: |awk '{print $2}'` 
  && sPPID=`cat /proc/$PID/status |grep ^PPid: |awk '{print $2}'` 
  && sTTY=`ls -alF /proc/$PID/fd |grep /dev/ |awk '{print $11}' |grep ty |head -n 1` 
  && sUID=`cat /proc/$PID/status |grep ^Uid: |awk '{print $2}'` 
  && sGID=`cat /proc/$PID/status |grep ^Gid: |awk '{print $2}'` 
  && sSTAT=`cat /proc/$PID/status |grep ^State: |awk '{print $2 $3}'` 
  && sMEM=`cat /proc/$PID/status |grep ^VmSize: |awk '{print $2 $3}'` 
  && if [ -e /proc/$PID/exe ] 
  then 
     sCMD=`ls -alF /proc/$PID/exe |awk '{print $11}' |tr -d '$*' ` 
  else 
     sCMD=`cat /proc/$PID/status |grep ^Name: |awk '{print $2}'` 
     sCMD="[ $sCMD ]" 
  fi 
  echo -e "$sPID $sPPID $sUID $sGID $sSTAT $sMEM $sTTY $sCMD" 
done 
简要介绍,这个lps或列举系统中自身进程(lps)之外的所有进程,然后读取和显示他们的八项属性,依次是:进程ID(PID) 父进程ID(PPID) 属主UID(UID) 属主GID(GID) 当前状态 占用内存 运行终端 完全执行路径。 
在显示格式参考了Linux标准ps输出的一部分,例如某些系统线程没有可执行文件的,就会显示他们的内核名字,例如[ ksoftirqd_CPU0 ] 。 
懒人的PS中没有任何参数,你也可以扩展它的功能,使之能支持按照进程树状显示等等。 
在我系统上的输出: 
代码: 
[elly@frost.llnl]/tmp# ./lps.sh 
PID     PPID    UID     GID     STAT            MEM     TTY     CMD 
1       0       0       0       S(sleeping)     1116kB          /sbin/init 
101     1       0       0       S(sleeping)     2168kB          /usr/local/sbin/sshd 
109     99      99      99      S(sleeping)     6100kB          /usr/local/apache/bin/httpd 
110     99      99      99      S(sleeping)     6100kB          /usr/local/apache/bin/httpd 
112     99      99      99      S(sleeping)     6100kB          /usr/local/apache/bin/httpd 
113     99      99      99      S(sleeping)     6100kB          /usr/local/apache/bin/httpd 
116     99      99      99      S(sleeping)     6100kB          /usr/local/apache/bin/httpd 
118     1       0       0       S(sleeping)     1656kB          /bin/bash 
119     1       0       0       S(sleeping)     1648kB          /bin/bash 
120     1       0       0       S(sleeping)     1648kB          /bin/bash 
128     1       0       0       S(sleeping)     2224kB  /dev/tty1       /bin/login 
1283    3113    0       0       S(sleeping)     1512kB  /dev/ttyp0      /bin/vi 
129     1       0       0       S(sleeping)     1136kB  /dev/tty2       /sbin/getty 
130     1       0       0       S(sleeping)     1136kB  /dev/tty3       /sbin/getty 
131     1       0       0       S(sleeping)     1136kB  /dev/tty4       /sbin/getty 
135     1       0       0       S(sleeping)     1136kB  /dev/tty5       /sbin/getty 
136     1       0       0       S(sleeping)     1136kB  /dev/tty6       /sbin/getty 
137     1       0       0       S(sleeping)     1140kB  /dev/ttyS0      /sbin/getty 
15329   3112    0       0       S(sleeping)     1792kB  /dev/ttyp1      /bin/bash 
2       1       0       0       S(sleeping)                     [ keventd ] 
256     128     0       0       S(sleeping)     1712kB  /dev/tty1       /bin/bash 
3       1       0       0       S(sleeping)                     [ ksoftirqd_CPU0 ] 
3112    101     0       0       S(sleeping)     2452kB  /dev/ptyp1      /usr/local/sbin/sshd 
3113    3112    0       0       S(sleeping)     1728kB  /dev/ttyp0      /bin/bash 
3872    120     0       0       S(sleeping)     1084kB          /bin/sleep 
4       1       0       0       S(sleeping)                     [ kswapd ] 
4       1       0       0       S(sleeping)                     [ kswapd ] 
4       1       0       0       S(sleeping)                     [ kswapd ] 
4089    15329   0       0       S(sleeping)     1664kB  /dev/ttyp1      /bin/bash 
4089    15329   0       0       S(sleeping)     1664kB  /dev/ttyp1      /bin/bash 
5       1       0       0       S(sleeping)                     [ bdflush ] 
6       1       0       0       S(sleeping)                     [ kupdated ] 
99      1       0       0       S(sleeping)     6016kB          /usr/local/apache/bin/httpd 
Solaris上有/usr/proc/bin工具集,里面的ptree和pmap很是好用,甚至比本来的ps还好:P可惜Linux上是没有的,现在你可以自己写一个,用来综合显示更多的进程状态。 
代码: 
#!/bin/bash 
#PROC=`mount |grep 'type proc'|awk '{print $3}'` 
test $1 || { echo "Usage: pstat.sh PID" && exit }; 
PID=$1; 
echo "Process $1 Status..."; 
echo "......................"; 
echo 
cat /proc/$PID/status|grep ^Name: 
cat /proc/$PID/status|grep ^Pid: 
cat /proc/$PID/status|grep ^PPid: 
cat /proc/$PID/status|grep ^Uid: 
cat /proc/$PID/status|grep ^Gid: 
cat /proc/$PID/status|grep ^State: 
cat /proc/$PID/status|grep ^VmSize: 
echo 
CMD=`ls -alF /proc/$PID/exe |awk '{print $11}' |tr -d '$*'`;echo "Command path: $CMD"; 
ARG=`cat /proc/$PID/cmdline`;echo "Command line: $ARG"; 
CWD=`ls -alF /proc/$PID/cwd |awk '{print $11}'`;echo "CWD: $CWD"; 
echo 
ENVI=`cat /proc/$PID/environ`;echo "ENVIRON: $ENVI"; 
echo 
echo 
echo "Process shared object:"; 
echo "......................"; 
cat /proc/$PID/maps |grep $CMD |grep xp; 
cat /proc/$PID/maps |grep .so |grep xp; 
echo 
echo 
echo "Process used file:"; 
echo "......................"; 
ls -alF /proc/$PID/fd |grep '->' |awk '{print $11}' |sort |uniq -c |sort -rn ; 
echo 
这个程序叫pstat.sh,可以显示进程的综合信息。输出分为四段,分别是进程状态(包含父子进程关系、进程信任状以及内存占用),执行环境(包含进程执行程序,命令行参数和环境变量),进程执行对象(包含进程执行体和引用的共享库),最后是进程打开的 所有文件。 
代码: 
[elly@frost.llnl]/tmp# ./pstat.sh 
Usage: pstat.sh PID 
[elly@frost.llnl]/tmp# ./pstat.sh 7238 
Process 7238 Status... 
...................... 
Name:   vi 
Pid:    7238 
PPid:   3113 
Uid:    0       0       0       0 
Gid:    0       0       0       0 
State:  S (sleeping) 
VmSize:     1648 kB 
Command path: /bin/vi 
Command line: vi 
CWD: /usr/ 
ENVIRON: USERNAME=root 
Process shared object: 
...................... 
08048000-08098000 r-xp 00000000 03:01 3891       /bin/vi 
40000000-40013000 r-xp 00000000 03:01 3942       /lib/ld-2.1.3.so 
40016000-40019000 r-xp 00000000 03:01 4002       /lib/libtermcap.so.2.0.8 
4001a000-40107000 r-xp 00000000 03:01 3949       /lib/libc-2.1.3.so 
4010f000-40117000 r-xp 00000000 03:01 3981       /lib/libnss_files-2.1.3.so 

Process used file: 
...................... 
/dev/ttyp0 
/etc/motd


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值