Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Cooper M.Advanced bash-scripting guide.2002.pdf
Скачиваний:
13
Добавлен:
23.08.2013
Размер:
916.67 Кб
Скачать

Chapter 28. /dev and /proc

A Linux or UNIX machine typically has two special−purpose directories, /dev and /proc.

28.1. /dev

The /dev directory contains entries for the physical devices that may or may not be present in the hardware. [56] The hard drive partitions containing the mounted filesystem(s) have entries in /dev, as a simple

df shows.

bash$ df

 

 

 

 

 

Filesystem

1k−blocks

Used Available Use%

 

Mounted on

 

 

 

 

 

/dev/hda6

495876

222748

247527

48%

/

/dev/hda1

50755

3887

44248

9%

/boot

/dev/hda8

367013

13262

334803

4%

/home

/dev/hda5

1714416

1123624

503704

70%

/usr

 

 

 

 

 

 

Among other things, the /dev directory also contains loopback devices, such as /dev/loop0. A loopback device is a gimmick allows an ordinary file to be accessed as if it were a block device. [57] This enables mounting an entire filesystem within a single large file. See Example 13−6 and Example 13−5.

A few of the pseudo−devices in /dev have other specialized uses, such as /dev/null, /dev/zero and

/dev/urandom.

28.2. /proc

The /proc directory is actually a pseudo−filesystem. The files in the /proc directory mirror currently running system and kernel processes and contain information and statistics about them.

bash$ cat /proc/devices

Character devices:

1mem

2pty

3ttyp

4ttyS

5cua

7vcs

10

misc

14

sound

29

fb

36

netlink

128

ptm

136

pts

162

raw

254

pcmcia

Block devices: 1 ramdisk

Chapter 28. /dev and /proc

275

Advanced Bash−Scripting Guide

2fd

3ide0

9md

bash$ cat /proc/interrupts

 

CPU0

 

0:

84505

XT−PIC timer

1:3375 XT−PIC keyboard

2:0 XT−PIC cascade

5:1 XT−PIC soundblaster

8:

1

XT−PIC rtc

12:4231 XT−PIC PS/2 Mouse

14:

109373

 

XT−PIC ide0

NMI:

 

0

 

 

ERR:

 

0

 

 

bash$

cat /proc/partitions

 

major

minor

#blocks

name

rio rmerge rsect ruse wio wmerge wsect wuse running use aveq

3

0

3007872

hda 4472 22260 114520 94240 3551 18703 50384 549710 0 111550 644030

3

1

52416

hda1 27 395 844 960 4 2 14 180 0 800 1140

3

2

1

hda2 0 0 0 0 0 0 0 0 0 0 0

3

4

165280

hda4 10 0 20 210 0 0 0 0 0 210 210

...

 

 

 

bash$ cat /proc/loadavg

0.13 0.42 0.27 2/44 1119

Shell scripts may extract data from certain of the files in /proc. [58]

kernel_version=$( awk '{ print $3 }' /proc/version )

CPU=$( awk '/model name/ {print $4}' < /proc/cpuinfo )

if [ $CPU = Pentium ] then

run_some_commands

...

else run_different_commands

...

fi

The /proc directory contains subdirectories with unusual numerical names. Every one of these names maps to the process ID of a currently running process. Within each of these subdirectories, there are a number of files that hold useful information about the corresponding process. The stat and status files keep running statistics on the process, the cmdline file holds the command−line arguments the process was invoked with, and the exe file is a symbolic link to the complete path name of the invoking process. There are a few more such files, but these seem to be the most interesting from a scripting standpoint.

Chapter 28. /dev and /proc

276

Advanced Bash−Scripting Guide

Example 28−1. Finding the process associated with a PID

#!/bin/bash

# pid−identifier.sh: Gives complete path name to process associated with pid.

ARGNO=1 # Number of arguments the script expects.

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 # Error message >stderr. exit $E_WRONGARGS

fi

pidno=$( ps ax | grep $1 | awk '{ print $1 }' | grep $1 )

#Checks for pid in "ps" listing, field #1.

#Then makes sure it is the actual process, not the process invoked by this script.

#The last "grep $1" filters out this possibility.

if [ −z "$pidno" ] # If, after all the filtering, the result is a zero−length string, then # no running process corresponds to the pid given.

echo "No such process running." exit $E_NOSUCHPROCESS

fi

#Alternatively:

#if ! ps $1 > /dev/null 2>&1

# then

# no running process corresponds to the pid given.

#echo "No such process running."

#exit $E_NOSUCHPROCESS

#fi

#To simplify the entire process, use "pidof".

if [ ! −r "/proc/$1/$PROCFILE" ] # Check for read permission. then

echo "Process $1 running, but..."

echo "Can't get read permission on /proc/$1/$PROCFILE."

exit $E_NOPERMISSION # Ordinary user can't access some files in /proc.

fi

#The last two tests may be replaced by:

#if ! kill −0 $1 > /dev/null 2>&1 # '0' is not a signal, but

#this will test whether it is possible

#to send a signal to the process.

#then echo "PID doesn't exist or you're not its owner" >&2

#exit $E_BADPID

#fi

exe_file=$( ls −l /proc/$1 | grep "exe" | awk '{ print $11 }' )

# Or exe_file=$( ls −l /proc/$1/exe | awk '{print $11}' )

#

#/proc/pid−number/exe is a symbolic link

#to the complete path name of the invoking process.

Chapter 28. /dev and /proc

277

Advanced Bash−Scripting Guide

if [ −e "$exe_file" ] # If /proc/pid−number/exe exists...

then # the corresponding process exists. echo "Process #$1 invoked by $exe_file."

else

echo "No such process running."

fi

#This elaborate script can *almost* be replaced by

#ps ax | grep $1 | awk '{ print $5 }'

#However, this will not work...

#because the fifth field of 'ps' is argv[0] of the process,

#not the executable file path.

#

#However, either of the following would work.

#find /proc/$1/exe −printf '%l\n'

#lsof −aFn −p $1 −d txt | sed −ne 's/^n//p'

#Additional commentary by Stephane Chazelas.

exit 0

Example 28−2. On−line connect status

#!/bin/bash

 

 

PROCNAME=pppd

# ppp daemon

 

PROCFILENAME=status

# Where to look.

 

NOTCONNECTED=65

 

 

INTERVAL=2

# Update every 2

seconds.

pidno=$( ps ax | grep −v "ps ax" | grep −v grep | grep $PROCNAME | awk '{ print $1 }' )

#Finding the process number of 'pppd', the 'ppp daemon'.

#Have to filter out the process lines generated by the search itself.

#However, as Oleg Philon points out,

#+ this could have been considerably simplified by using "pidof".

#pidno=$( pidof $PROCNAME )

#Moral of the story:

#+ When a command sequence gets too complex, look for a shortcut.

if [ −z "$pidno" ] # If no pid, then process is not running. then

echo "Not connected." exit $NOTCONNECTED

else

echo "Connected."; echo

fi

 

while [ true ]

# Endless loop, script can be improved here.

do

 

if [ ! −e "/proc/$pidno/$PROCFILENAME" ]

# While process running, then "status" file exists. then

echo "Disconnected." exit $NOTCONNECTED

fi

Chapter 28. /dev and /proc

278

Advanced Bash−Scripting Guide

netstat −s | grep "packets received" # Get some connect statistics. netstat −s | grep "packets delivered"

sleep $INTERVAL echo; echo

done

exit 0

#As it stands, this script must be terminated with a Control−C.

#Exercises for the reader:

#Improve the script so it exits on a "q" keystroke.

#Make the script more user−friendly in other ways.

In general, it is dangerous to write to the files in /proc, as this can corrupt the filesystem or crash the machine.

Chapter 28. /dev and /proc

279