- •Table of Contents
- •Chapter 1. Why Shell Programming?
- •2.1. Invoking the script
- •2.2. Preliminary Exercises
- •Part 2. Basics
- •Chapter 3. Exit and Exit Status
- •Chapter 4. Special Characters
- •Chapter 5. Introduction to Variables and Parameters
- •5.1. Variable Substitution
- •5.2. Variable Assignment
- •5.3. Bash Variables Are Untyped
- •5.4. Special Variable Types
- •Chapter 6. Quoting
- •Chapter 7. Tests
- •7.1. Test Constructs
- •7.2. File test operators
- •7.3. Comparison operators (binary)
- •7.4. Nested if/then Condition Tests
- •7.5. Testing Your Knowledge of Tests
- •Chapter 8. Operations and Related Topics
- •8.1. Operators
- •8.2. Numerical Constants
- •Part 3. Beyond the Basics
- •Chapter 9. Variables Revisited
- •9.1. Internal Variables
- •9.2. Manipulating Strings
- •9.2.1. Manipulating strings using awk
- •9.2.2. Further Discussion
- •9.3. Parameter Substitution
- •9.4. Typing variables: declare or typeset
- •9.5. Indirect References to Variables
- •9.6. $RANDOM: generate random integer
- •9.7. The Double Parentheses Construct
- •Chapter 10. Loops and Branches
- •10.1. Loops
- •10.2. Nested Loops
- •10.3. Loop Control
- •10.4. Testing and Branching
- •Chapter 11. Internal Commands and Builtins
- •11.1. Job Control Commands
- •Chapter 12. External Filters, Programs and Commands
- •12.1. Basic Commands
- •12.2. Complex Commands
- •12.3. Time / Date Commands
- •12.4. Text Processing Commands
- •12.5. File and Archiving Commands
- •12.6. Communications Commands
- •12.7. Terminal Control Commands
- •12.8. Math Commands
- •12.9. Miscellaneous Commands
- •Chapter 13. System and Administrative Commands
- •Chapter 14. Command Substitution
- •Chapter 15. Arithmetic Expansion
- •Chapter 16. I/O Redirection
- •16.1. Using exec
- •16.2. Redirecting Code Blocks
- •16.3. Applications
- •Chapter 17. Here Documents
- •Chapter 18. Recess Time
- •Part 4. Advanced Topics
- •Chapter 19. Regular Expressions
- •19.1. A Brief Introduction to Regular Expressions
- •19.2. Globbing
- •Chapter 20. Subshells
- •Chapter 21. Restricted Shells
- •Chapter 22. Process Substitution
- •Chapter 23. Functions
- •23.1. Complex Functions and Function Complexities
- •23.2. Local Variables
- •23.2.1. Local variables make recursion possible.
- •Chapter 24. Aliases
- •Chapter 25. List Constructs
- •Chapter 26. Arrays
- •Chapter 27. Files
- •Chapter 28. /dev and /proc
- •28.2. /proc
- •Chapter 29. Of Zeros and Nulls
- •Chapter 30. Debugging
- •Chapter 31. Options
- •Chapter 32. Gotchas
- •Chapter 33. Scripting With Style
- •33.1. Unofficial Shell Scripting Stylesheet
- •Chapter 34. Miscellany
- •34.2. Shell Wrappers
- •34.3. Tests and Comparisons: Alternatives
- •34.4. Optimizations
- •34.5. Assorted Tips
- •34.6. Oddities
- •34.7. Portability Issues
- •34.8. Shell Scripting Under Windows
- •Chapter 35. Bash, version 2
- •Chapter 36. Endnotes
- •36.1. Author's Note
- •36.2. About the Author
- •36.3. Tools Used to Produce This Book
- •36.3.1. Hardware
- •36.3.2. Software and Printware
- •36.4. Credits
- •Bibliography
- •Appendix A. Contributed Scripts
- •Appendix C. Exit Codes With Special Meanings
- •Appendix D. A Detailed Introduction to I/O and I/O Redirection
- •Appendix E. Localization
- •Appendix F. History Commands
- •Appendix G. A Sample .bashrc File
- •Appendix H. Converting DOS Batch Files to Shell Scripts
- •Appendix I. Exercises
- •Appendix J. Copyright
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 |