第二十七章 /dev 和 /proc
27.1 /dev
在/dev目录内包含以或不以硬件形式出现的物理设备条目。包含被挂载的文件系统的硬设备分区在/dev目录下都有对应的条目,就像 df 命令所展示的。
[root@mail shell]# df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/mapper/centos-root 17811456 4809860 13001596 28% /
devtmpfs 929248 0 929248 0% /dev
tmpfs 941176 0 941176 0% /dev/shm
tmpfs 941176 8636 932540 1% /run
tmpfs 941176 0 941176 0% /sys/fs/cgroup
/dev/vda1 1038336 147840 890496 15% /boot
tmpfs 188236 0 188236 0% /run/user/0
在其他方面,/dev目录也包含环回设备,例如/dev/loop0。环回设备是一个使普通文件能被像对待块设备一样来进行存取的机制。这使我们可以将一个大文件内的整个文件系统挂载到系统目录下。
/dev还有少量的伪设备用于特殊的用途,
例如:/dev/null,/dev/zero,/dev/urandom,/dev/sda1,/dev/udp,/dev/tcp
例如:为了挂载一个USB闪盘设备,将下面一行添加到/etc/fstab
/dev/sda1 /mnt/flashdrive auto noauto,user,noatime 0 0
当对/dev/tcp/$host/$port 伪设备文件执行一个命令时,Bash 会打开一个相关的 TCP 的 socket。
Example 27-1 利用/dev/tcp来检修故障(复制粘贴的)
#!/bin/bash
#
TCP_HOST=www.baidu.com
TCP_PORT=80
echo "HEAD / HTTP/1.0" >/dev/tcp/${TCP_HOST}/${TCP_PORT}
MYEXIT=$?
: << EXPLANATION
If bash was compiled with --enable-net-redirections, it has the capability of
using a special character device for both TCP and UDP redirections. These
redirections are used identically as STDIN/STDOUT/STDERR. The device entries
are 30,36 for /dev/tcp:
mknod /dev/tcp c 30 36
>From the bash reference:
/dev/tcp/host/port
If host is a valid hostname or Internet address, and port is an integer
port number or service name, Bash attempts to open a TCP connection to the
corresponding socket.
EXPLANATION
if [ "X$MYEXIT" = "X0" ]; then
echo "Connection successful. Exit code: $MYEXIT"
else
echo "Connection unsuccessful. Exit code: $MYEXIT"
fi
exit $MYEXIT
27.2 /proc
/proc目录实际上是一个伪文件系统。在/proc目录里的文件是当前运行系统和内核及它们的相关信息和统计
[root@zhhs-mail ~]# cat /proc/devices
Character devices:
1 mem
4 /dev/vc/0
...
5 /dev/console
5 /dev/ptmx
...
253 device-mapper
254 mdp
[root@zhhs-mail ~]# cat /proc/interrupts
CPU0
0: 81 IO-APIC-edge timer
1: 10 IO-APIC-edge i8042
4: 1176 IO-APIC-edge serial
...
NPI: 0 Nested posted-interrupt event
PIW: 0 Posted-interrupt wakeup event
[root@zhhs-mail ~]# cat /proc/partitions
major minor #blocks name
252 0 20971520 vda
252 1 1048576 vda1
252 2 19921920 vda2
11 0 1048575 sr0
253 0 17821696 dm-0
253 1 2097152 dm-1
[root@zhhs-mail ~]# cat /proc/loadavg
0.00 0.01 0.05 1/110 30207
Shell脚本可从/proc目录中的一些文件里提取数据
FS=iso
grep $FS /proc/filesystems
kernel_version=$(awk '{print $3}' /proc/version)
CPU=$(awk '/mode name/ {print $4}' < /proc/cpuinfo)
if [ $CPU = Pentium ];then
run_some_commands
else
run_different_commands
fi
devfile="/proc/bus/usb/devices"
USB1="Spd=12"
USB2="Spd=480"
bus_speed=$(grep Spd $devfile | awk '{print $9}')
if [ "$bus_speed" = "$USB1" ];then
echo "USB 1.1 port found"
fi
/proc 目录下有许多不相同的数字命名的子目录。这些子目录的数字名字都映射对应的当前正在运行的进程的进程号。这些子目录里面有许多文件用于保存对应进程的信息。文件 stat 和 status 保存着进程运行时的各项统计,the cmdline 文件保存该进程的被调用 时的命令行参数,而 and the exe 文件是该运行进程完整路径名的符号链接。还有其他一些文件,但从脚本的观点来看它们都非常的有意思。
Example 27-2 搜索一个与PID相关的进程
#!/bin/bash
#
ARGNO=1
E_WRONGARGS=65
E_BADPID=66
E_NOSUCHPROCESS=67
E_NOPERMISSION=68
PROCFILE=exe
if [ $# -ne $ARGNO ];then
echo "Usage: `basename $0` PID-number" >&2
exit $E_WRONGARGS
fi
pidno=$(ps ax | grep $1 | awk '{print $1}' | grep $1)
if [ -z "$pidno" ];then
echo "No such process running."
exit $E_NOSUCHPROCESS
fi
if [ ! -r "/proc/$1/$PROCFILE" ];then
echo "Process $1 running, but..."
echo "Can't get read permission on /proc/$1/$PROCFILE."
exit $E_NOPERMISSION
fi
exe_file=$(ls -l /proc/$1 | grep "exe" | awk '{print $11}')
if [ -e "$exe_file" ];then
echo "Process #$1 invoked by $exe_file."
else
echo "No such process running."
fi
exit 0
Example 27-3 网络连接状态
#!/bin/bash
#
PROCNAME=postfix
PROCFILENAME=status
NOTCONNECTED=65
INTERVAL=2
pidno=$(ps ax | grep -v "ps ax" | grep -v grep | grep $PROCNAME |awk '{print $1}')
if [ -z "$pidno" ];then
echo "Not connected."
exit $NOTCONNECTED
else
echo "Connected."; echo
fi
while [ true ]
do
if [ ! -e "/proc/$pidno/$PROCFILENAME" ];then
echo "Disconnected."
exit $NOTCONNECTED
fi
netstat -s | grep "packets received"
netstat -s | grep "packets delivered"
sleep $INTERVAL
echo;echo
done
exit 0
注意:一般来说,写/proc 目录里的文件是危险,因为这样会破坏这个文件系统或摧毁机器。