参考链接:
Linux proc详解
linux proc目录
Linux Filesystem Hierarchy
在Linux中存在着一类特殊的伪文件系统,用于使用与文件接口统一的操作来完成各种功能,例如ptyfs、devfs、sysfs和procfs。而procfs就是其中应用最广泛的一种伪文件系统。
就文件系统这一术语而言,/ proc目录并不是真正的文件系统,它是一个虚拟文件系统,有时也被称为进程信息伪文件系统。
proc 放置的数据都是在内存当中,例如系统内核、进程、外部设备的状态及网络状态等。因为这个目录下的数据都是在内存当中,所以本身不占任何硬盘空间。
procfs是Linux内核信息的抽象文件接口,大量内核中的信息以及可调参数都被作为常规文件映射到一个目录树中,这样我们就可以简单直接的通过echo或cat这样的文件操作命令对系统信息进行查取和调整了。同时procfs也提供了一个接口,使得我们自己的内核模块或用户态程序可以通过procfs进行参数的传递。在当今的Linux系统中,大量的系统工具也通过procfs获取内核参数,例如ps、lspci等等,没有procfs它们将可能不能正常工作。
文件名 | 文件内容 |
---|---|
/proc/cmdline | 加载kernel时所执行的相关参数。此文件可帮助了解系统是如何启动的 |
/proc/cpuinfo | 本机的CPU相关信息,包含频率、类型与运算功能等 |
/proc/devices | 记录了系统各个主要设备的主要设备代号,与mknod有关 |
/proc/filesystems | 目前系统已经加载的文件系统 |
/proc/interrupts | 目前系统的IRQ分配状态 |
/proc/ioports | 目前系统的各个设备所配置的IO地址 |
/proc/kcore | 内存的大小 |
/proc/loadavg | top和uptime上面的三个平均数值 |
/proc/meminfo | 使用free列出的内存信息,在这也能查阅 |
/proc/mounts | 系统已经挂载的数据,就是用mount命令调出来的数据 |
/proc/swaps | 系统加载的内存,使用的分区记录 |
/proc/partitions | 使用fdisk -l会出现目前所有的分区,这个文件中也有记录 |
挂在
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
进程相关部分 (只读)
这部分文件都是以数字为名的子目录,这个数字就是相关进程的进程ID,在 1.1节中会详细介绍进程相关子目录的结构和信息。
需要注意的是procfs中进程子系统部分的一个特殊点,就是/proc/self,它是指向当前执行进程的符号连接,或者说–是指向未来你将要执行指令的心灵感应:
$ cat /proc/self/cmdline
cat/proc/self/cmdline%
在这个命令中,我们希望它显示当前进程的cmdline参数,它恰恰就显示了当前进程–我们所执行的这条命令,cat self/cmdline。幸好这条指令显示出的信息会忽略空格,导致显示略微的不正常,否则我们倒是可以很容易的使用cat self/cmdline
这样的命令制造出永远循环执行的进程来。
内核信息部分 (只读)
这部分文件同样处于/proc的顶层目录,不过它们大部分都是常规、只读的文本文件,可以直接用cat查看信息。作为系统内核执行体的抽象,我们也可以把它看作内核"进程"的信息部分,当然虽然并不存在这个进程实体。这里比较特别的一个文件是 /proc/cmdline :
$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-4.4.0-21-generic root=UUID=43682bbc-6095-48f0-bf10-41575ac90aca ro quiet splash vt.handoff=7
在这个文件中存放的是系统内核引导时的命令行参数。
内核各子系统相关部分 (部分可调)
这部分是系统内核参数调整的重头戏,在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保存配置以在下次启动时自动加载这些设置。
1.1 进程相关子目录
在/proc目录中包含了一些以数字为名的子目录,这些目录就是系统当前运行进程的proc抽象。每一个目录都以相关联的活动系统进程PID为目录名,在目录下包含了一些文件,用于显示进程相关的信息。每个进程映射子目录的结构都如下:
文件名 | 内容 |
---|---|
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
cat self/status
Name: cat
State: R (running)
Tgid: 26794
Ngid: 0
Pid: 26794
PPid: 13935
TracerPid: 0
Uid: 1000 1000 1000 1000
Gid: 1000 1000 1000 1000
FDSize: 64
Groups: 4 24 27 30 46 113 128 1000
NStgid: 26794
NSpid: 26794
NSpgid: 26794
NSsid: 13935
VmPeak: 9188 kB
VmSize: 9188 kB
VmLck: 0 kB
VmPin: 0 kB
VmHWM: 676 kB
VmRSS: 676 kB
VmData: 316 kB
VmStk: 140 kB
VmExe: 48 kB
VmLib: 1944 kB
VmPTE: 40 kB
VmPMD: 12 kB
VmSwap: 0 kB
HugetlbPages: 0 kB
Threads: 1
SigQ: 0/31220
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000000
SigCgt: 0000000000000000
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000
Seccomp: 0
Cpus_allowed: f
Cpus_allowed_list: 0-3
Mems_allowed: 00000000,00000001
Mems_allowed_list: 0
voluntary_ctxt_switches: 0
nonvoluntary_ctxt_switches: 1
如同第一节所说,/proc/self连接指向读取它自身的进程映像。
这条命令显示的信息与你通过 /bin/ps 命令获取到的进程信息基本相同,这恰巧是因为,ps也是通过读取procfs来获取这些信息的。statm 文件包含了更详细的进程内存状态,statm的详细内容按照数据项由左向右依次如下.
$ cat /proc/self/statm
2297 194 177 12 0 114 0
数据项 | 内容 |
---|---|
size | 程序大小 |
resident | 常驻内存空间大小 |
shared | 共享内存页数 |
trs | 代码段占用内存页数 |
drs | 数据/堆栈段占用内存页数 |
lrs | 引用库占用内存页数 |
dt | 脏页数量 |
1.2 内核数据
相似于进程入口,在/proc目录下的其他一些文件给出了内核信息数据,这些文件包含了系统当前运行内核相关信息。/proc目录下内核相关信息文件在下表中列出,依赖于您的系统配置和加载的内核模块,在您的系统中的显示可能会略有不同。
文件 | 内容 |
---|---|
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*目录中我们可以得到更多的信息,如下表.
文件名 | 内容 |
---|---|
channel | IDE通道 (0 or 1) |
config | 配置 (only for PCI/IDE bridge) |
mate | Mate name |
model | IDE控制器的类型/芯片组 |
hd? | IDE总线上连接的可用设备 |
当前连接在控制器上的每个设备也将成为一个单独的子目录,如下表.
文件名 | 内容 |
---|---|
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 子目录包含了系统中网络相关的内核统计信息和视图, 如果你的内核支持IPV6,那么还有一些IPV6相关信息在下表:
文件名 | 内容 |
---|---|
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