Michael ffirs.tex V2 - 03/24/2008 4:19pm Page iii ® Mastering UNIX Shell Scripting Bash, Bourne, and Korn Shell Scripting for Programmers, System Administrators, and UNIX Gurus Second Edition Randal K Michael Wiley Publishing, Inc Michael ffirs.tex V2 - 03/24/2008 4:19pm Page ii Michael ffirs.tex V2 - 03/24/2008 4:19pm Page i Mastering UNIX®Shell Scripting Second Edition Michael ffirs.tex V2 - 03/24/2008 4:19pm Page ii Michael ffirs.tex V2 - 03/24/2008 4:19pm Page iii ® Mastering UNIX Shell Scripting Bash, Bourne, and Korn Shell Scripting for Programmers, System Administrators, and UNIX Gurus Second Edition Randal K Michael Wiley Publishing, Inc Michael ffirs.tex V2 - 03/24/2008 4:19pm Page iv Mastering UNIX®Shell Scripting: Bash, Bourne, and Korn Shell Scripting for Programmers, System Administrators, and UNIX Gurus, Second Edition Published by Wiley Publishing, Inc 10475 Crosspoint Boulevard Indianapolis, IN 46256 www.wiley.com Copyright © 2008 by Randal K Michael Published by Wiley Publishing, Inc., Indianapolis, Indiana Published simultaneously in Canada ISBN: 978-0-470-18301-4 Manufactured in the United States of America 10 No part of this publication may be reproduced, stored in a retrieval system or transmitted in any form or by any means, electronic, mechanical, photocopying, recording, scanning or otherwise, except as permitted under Sections 107 or 108 of the 1976 United States Copyright Act, without either the prior written permission of the Publisher, or authorization through payment of the appropriate per-copy fee to the Copyright Clearance Center, 222 Rosewood Drive, Danvers, MA 01923, (978) 750-8400, fax (978) 646-8600 Requests to the Publisher for permission should be addressed to the Legal Department, Wiley Publishing, Inc., 10475 Crosspoint Blvd., Indianapolis, IN 46256, (317) 572-3447, fax (317) 572-4355, or online at http://www.wiley.com/go/permissions Limit of Liability/Disclaimer of Warranty: The publisher and the author make no representations or warranties with respect to the accuracy or completeness of the contents of this work and specifically disclaim all warranties, including without limitation warranties of fitness for a particular purpose No warranty may be created or extended by sales or promotional materials The advice and strategies contained herein may not be suitable for every situation This work is sold with the understanding that the publisher is not engaged in rendering legal, accounting, or other professional services If professional assistance is required, the services of a competent professional person should be sought Neither the publisher nor the author shall be liable for damages arising herefrom The fact that an organization or Website is referred to in this work as a citation and/or a potential source of further information does not mean that the author or the publisher endorses the information the organization or Website may provide or recommendations it may make Further, readers should be aware that Internet Websites listed in this work may have changed or disappeared between when this work was written and when it is read For general information on our other products and services or to obtain technical support, please contact our Customer Care Department within the U.S at (800) 762-2974, outside the U.S at (317) 572-3993 or fax (317) 572-4002 Library of Congress Cataloging-in-Publication Data is available from publisher Trademarks: Wiley, the Wiley logo, and related trade dress are trademarks or registered trademarks of John Wiley & Sons, Inc and/or its affiliates, in the United States and other countries, and may not be used without written permission UNIX is a registered trademark of The Open Group All other trademarks are the property of their respective owners Wiley Publishing, Inc., is not associated with any product or vendor mentioned in this book Wiley also publishes its books in a variety of electronic formats Some content that appears in print may not be available in electronic books Michael ffirs.tex V2 - 03/24/2008 4:19pm Page v This book is dedicated to my wife Robin, the girls, Andrea and Ana, and the grandchildren, Gavin, Jocelyn, and Julia — my true inspiration Michael ffirs.tex V2 - 03/24/2008 4:19pm Page vi Michael fabout.tex V1 - 03/24/2008 4:34pm Page vii About the Author Randal K Michael is a UNIX Systems Administrator working as a contract consultant He teaches UNIX shell scripting in corporate settings, where he writes shell scripts to address a variety of complex problems and tasks, ranging from monitoring systems to replicating large databases He has more than 30 years of experience in the industry and 15 years of experience as a UNIX Systems Administrator, working on AIX, HP-UX, Linux, OpenBSD, and Solaris vii Michael fabout.tex V1 - 03/24/2008 4:34pm Page viii Michael 58 Part I ■ c01.tex V4 - 03/24/2008 4:45pm Page 58 The Basics of Shell Scripting The output of this simple menu is shown here: SYSTEM INFORMATION MENU 1) OS 3) Filesystems 5) Users 2) Host 4) Date 6) Quit Select an option and press Enter: Linux Press Enter to Continue Removing Repeated Lines in a File The uniq command is used to report and remove repeated lines in a file This is a valuable tool for a lot of scripting and testing If you have a file that has repeated lines named my_list and you want to save the list without the repeated lines in a file called my_list_no_repeats, use the following command: # uniq my_list my_list_no_repeats If you want to see a file’s output without repeated lines, use the following command: # cat repeat_file | uniq Removing Blank Lines from a File The easiest way to remove blank lines from a file is to use a sed statement The following syntax removes the blank lines: # cat my_file | sed /^$/d or # sed /^$/d my_file Testing for a Null Variable Variables that have nothing assigned to them are sometimes hard to deal with The following test will ensure that a variable is either Null or has a value assigned to it The double quotes are very important and must be used! Michael Chapter VAL= ■ c01.tex V4 - 03/24/2008 4:45pm Page 59 Scripting Quick Start and Review # Creates a NULL variable if [[ -z "$VAL" && "$VAL" = ’’ ]] then echo "The VAL variable is NULL" fi or VAL=25 if [[ ! -z "$VAL" && "$VAL" != ’’ ]] then echo "The VAL variable is NOT NULL" fi Directly Access the Value of the Last Positional Parameter, $# To access the value of the $# positional parameter directly, use the following regular expression: eval ’$’$# or eval \$$# There are a lot of uses for this technique, as you will see later in this book Remove the Column Headings in a Command Output There are many instances when we want to get rid of the column headings in a command’s output A lot of people try to use grep -v to pattern-match on something unique in the heading A much easier and more reliable method is to use the tail command An example is shown here with the df command output: [root:yogi]@/scripts# df -k Filesystem 1024-blocks /dev/hd4 32768 /dev/hd2 1466368 /dev/hd9var 53248 /dev/hd3 106496 /dev/hd1 4096 Free %Used 15796 52% 62568 96% 8112 85% 68996 36% 3892 5% Iused %Iused Mounted on 1927 12% / 44801 13% /usr 1027 8% /var 245 1% /tmp 55 6% /home 59 Michael 60 Part I ■ c01.tex V4 - 03/24/2008 4:45pm Page 60 The Basics of Shell Scripting /proc /dev/hd10opt /dev/scripts_lv /dev/lv_temp 655360 102400 409600 16420 98% 24012 77% 147452 65% 16261 1137 29 - /proc 10% /opt 5% /scripts 1% /tmpfs Now look at the same output with the column headings removed: [root:yogi]@/scripts# df -k | tail +2 /dev/hd4 32768 15796 /dev/hd2 1466368 62568 /dev/hd9var 53248 8112 /dev/hd3 106496 68996 /dev/hd1 4096 3892 /proc /dev/hd10opt 655360 16420 /dev/scripts_lv 102400 24012 /dev/lv_temp 409600 147452 52% 96% 85% 36% 5% 98% 77% 65% 1927 44801 1027 245 55 16261 1137 29 12% / 13% /usr 8% /var 1% /tmp 6% /home - /proc 10% /opt 5% /scripts 1% /tmpfs Just remember to add one to the total number of lines that you want to remove Arrays The shell supports one-dimensional arrays The maximum number of array elements is 1,024 When an array is defined, it is automatically dimensioned to 1,024 elements A one-dimensional array contains a sequence of array elements, which are like the boxcars connected together on a train track An array element can be just about anything, except for another array I know; you’re thinking that you can use an array to access an array to create two- and three-dimensional arrays This can be done, but it is beyond the scope of this book Loading an Array An array can be loaded in two ways You can define and load the array in one step with the set -A command, or you can load the array one element at a time Both techniques are shown here: set -A MY_ARRAY alpha beta gamma or X=0 # Initialize counter to zero # Load the array with the strings alpha, beta, and gamma for ELEMENT in alpha gamma beta MY_ARRAY[$X]=$ELEMENT ((X = X + 1)) done Michael Chapter ■ c01.tex V4 - 03/24/2008 4:45pm Page 61 Scripting Quick Start and Review The first array element is referenced by 0, not To access array elements use the following syntax: echo ${MY_ARRAY[2] gamma # Show the third array element echo ${MY_ARRAY[*] alpha beta gamma # Show all array elements echo ${MY_ARRAY[@] alpha beta gamma # Show all array elements echo ${#MY_ARRAY[*]} # Show the total number of array elements echo ${#MY_ARRAY[@]} # Show the total number of array elements echo ${MY_ARRAY} alpha # Show array element (the first element) We will use arrays in shell scripts in several chapters in this book Testing a String One of the hardest things to in a shell script is to test the user’s input from the command line The shell script shown in Listing 1-25 will the trick using regular expressions to define the string composition #!/bin/ksh # # SCRIPT: test_string.ksh # AUTHOR: Randy Michael # REV: 1.0.D - Used for developement # DATE: 10/15/2007 # PLATFORM: Not Platform Dependent # # PURPOSE: This script is used to test a character # string, or variable, for its composition # Examples include numeric, lowercase or uppercase # characters, alpha-numeric characters, and IP address # # REV LIST: # # # set -x # Uncomment to debug this script Listing 1-25 test_string.ksh shell script 61 Michael 62 Part I ■ c01.tex V4 - 03/24/2008 4:45pm Page 62 The Basics of Shell Scripting # set -n # Uncomment to verify syntax without any execution # # REMEMBER: Put the comment back or the script will # # NOT EXECUTE! # #################################################### ############## DEFINE FUNCTIONS HERE ############### #################################################### test_string () { # This function tests a character string # Must have one argument ($1) if (( $# != )) then # This error would be a programming error print "ERROR: $(basename $0) requires one argument" return fi # Assign arg1 to the variable > STRING STRING=$1 # This is where the string test begins case $STRING in +([0-9]).+([0-9]).+([0-9]).+([0-9])) # Testing for an IP address - valid and invalid INVALID=FALSE # Separate the integer portions of the "IP" address # and test to ensure that nothing is greater than 255 # or it is an invalid IP address for i in $(echo $STRING | awk -F ’{print $1, $2, $3, $4}’) if (( i > 255 )) then INVALID=TRUE fi done case $INVALID in TRUE) print ’INVALID_IP_ADDRESS’ ;; Listing 1-25 (continued) Michael Chapter ■ c01.tex V4 - 03/24/2008 4:45pm Page 63 Scripting Quick Start and Review FALSE) print ’VALID_IP_ADDRESS’ ;; esac ;; +([0-1])) # Testing for 0-1 only print ’BINARY_OR_POSITIVE_INTEGER’ ;; +([0-7])) # Testing for 0-7 only print ’OCTAL_OR_POSITIVE_INTEGER’ ;; +([0-9])) # Check for an integer print ’INTEGER’ ;; +([-0-9])) # Check for a negative whole number print ’NEGATIVE_WHOLE_NUMBER’ ;; +([0-9]|[.][0-9])) # Check for a positive floating point number print ’POSITIVE_FLOATING_POINT’ ;; +(+[0-9][.][0-9])) # Check for a positive floating point number # with a + prefix print ’POSITIVE_FLOATING_POINT’ ;; +(-[0-9][.][0-9])) # Check for a negative floating point number print ’NEGATIVE_FLOATING_POINT’ ;; +([-.0-9])) # Check for a negative floating point number print ’NEGATIVE_FLOATING_POINT’ ;; +([+.0-9])) # Check for a positive floating point number print ’POSITIVE_FLOATING_POINT’ ;; +([a-f])) # Test for hexidecimal or all lowercase characters print ’HEXIDECIMAL_OR_ALL_LOWERCASE’ ;; +([a-f]|[0-9])) # Test for hexidecimal or all lowercase characters print ’HEXIDECIMAL_OR_ALL_LOWERCASE_ALPHANUMERIC’ ;; +([A-F])) # Test for hexidecimal or all uppercase characters print ’HEXIDECIMAL_OR_ALL_UPPERCASE’ ;; +([A-F]|[0-9])) # Test for hexidecimal or all uppercase characters print ’HEXIDECIMAL_OR_ALL_UPPERCASE_ALPHANUMERIC’ Listing 1-25 (continued) 63 Michael 64 Part I ■ c01.tex V4 - 03/24/2008 4:45pm Page 64 The Basics of Shell Scripting ;; +([a-f]|[A-F])) # Testing for hexidecimal or mixed-case characters print ’HEXIDECIMAL_OR_MIXED_CASE’ ;; +([a-f]|[A-F]|[0-9])) # Testing for hexidecimal/alpha-numeric strings only print ’HEXIDECIMAL_OR_MIXED_CASE_ALPHANUMERIC’ ;; +([a-z]|[A-Z]|[0-9])) # Testing for any alpha-numeric string only print ’ALPHA-NUMERIC’ ;; +([a-z])) # Testing for all lowercase characters only print ’ALL_LOWERCASE’ ;; +([A-Z])) # Testing for all uppercase numbers only print ’ALL_UPPERCASE’ ;; +([a-z]|[A-Z])) # Testing for mixed case alpha strings only print ’MIXED_CASE’ ;; *) # None of the tests matched the string composition print ’INVALID_STRING_COMPOSITION’ ;; esac } #################################################### usage () { echo "\nERROR: Please supply one character string or variable\n" echo "USAGE: $THIS_SCRIPT {character string or variable}\n" } #################################################### ############# BEGINNING OF MAIN #################### #################################################### # Query the system for the name of this shell script # This is used for the "usage" function THIS_SCRIPT=$(basename $0) # Check for exactly one command-line argument Listing 1-25 (continued) Michael Chapter ■ c01.tex V4 - 03/24/2008 4:45pm Page 65 Scripting Quick Start and Review if (( $# != )) then usage exit fi # Everything looks okay if we got here Assign the # single command-line argument to the variable "STRING" STRING=$1 # Call the "test_string" function to test the composition # of the character string stored in the $STRING variable test_string $STRING # End of script Listing 1-25 (continued) This is a good start, but this shell script does not cover everything Play around with it to see if you can make some improvements N O T E Bash shell does not support the +([0-9])-type regular expressions Summary This chapter is just a primer to get you started with a quick review and some little tricks and tips In the next 27 chapters, we are going to write a lot of shell scripts to solve some real-world problems Sit back and get ready to take on the UNIX world! The first thing that we are going to study is 24 ways to process a file line-by-line I have seen a lot of good and bad techniques for processing a file line-by-line over the past 15 years, and some have been rather inventive The next chapter presents the 24 techniques that I have seen the most; at the end of the chapter there is a shell script that times each technique to find the fastest Read on, and find out which one wins the race See you in the next chapter! 65 Michael c01.tex V4 - 03/24/2008 4:45pm Page 66 Michael c02.tex V4 - 03/24/2008 4:48pm Page 67 CHAPTER 24 Ways to Process a File Line-by-Line Have you ever created a really slick shell script to process file data and found that you have to wait until after lunch to get the results? The script may be running so slowly because of how you are processing the file Over my many years of UNIX administration I have seen some rather, well, let’s call them creative ways to process a file line-by-line I have listed 24 of these methods in this chapter Some techniques are very fast, and some make you wait for half a day Then there are a few that, on first look, should work but not The techniques used in this chapter are measurable, and I created a shell script that will time each method so that you can see which method suits your needs When processing an ASCII text/data file, we are normally inside a loop of some kind Then, as we go through the file from the top to the bottom, we process each line of text A UNIX shell script is really not meant to work on a text file character-by-character (Pearl is better for this), but you can accomplish the task using various techniques The task for this chapter is to show the line-by-line parsing techniques by parsing each entire line at once, not character by character We are also going to look at using file descriptors as a method of file input and output redirection for file processing Command Syntax First, as always, we need to go over the command syntax that we are going to use The commands that we want to concentrate on in this chapter have to deal with while and for loops When parsing a file in a loop, we need a method to read in the entire line of data to a variable The most prevalent command is read The read command is flexible in that you can extract individual strings as well as the entire line Speaking of lines, the line command is another alternative to grab a full line of text Some operating 67 Michael 68 Part I ■ c02.tex V4 - 03/24/2008 4:48pm Page 68 The Basics of Shell Scripting systems not support the line command For example, the line command is not available on OpenBSD and some versions of Linux and Solaris In addition to the read and line commands, we need to look at the different ways to use the while and for loops, which is the major cause of fast or slow execution times A loop can be used as a standalone loop in a predefined configuration; it can be used in a command pipe or with file descriptors Each method has its own set of rules The use of the loop is critical to get the quickest execution times Using File Descriptors Under the covers of the UNIX operating system, files are referenced, copied, and moved by unique numbers known as file descriptors You already know about three of these file descriptors: - stdin - stdout - stderr We redirect output using the stdout (standard output) and stderr (standard error) a lot in this book, using several different techniques This is the first time we are going to use the stdin (standard input) file descriptor For a short definition of each of these we can talk about the devices on the computer Standard input usually comes into the computer from the keyboard or mouse Standard output usually has output to the screen or to a file Standard error is where commands, programs, and scripts route error messages We have used stderr before to send the error messages to the bit bucket, or /dev/null, and (more commonly) to combine the stdout and stderr outputs together You should remember a command like the following one: some_command 2>&1 The preceding command sends all the error messages to the same output device that standard output goes to, which is normally the terminal We can also use other file descriptors Valid descriptor values range from to 19 on most operating systems You have to a lot of testing when you use the upper values to ensure that they are not reserved by the system for some reason You will see more on using file descriptors in some of the following code listings Creating a Large File to Use in the Timing Test Before I get into each method of parsing the file, I want to show you a little script you can use to create a file of random alphanumeric characters that is exactly a user-specified number of MB in size The number of characters per line is 80, including the new-line character The method to create a file of random alphanumeric characters is to load an array with upper- and lowercase alpha characters as well as the numbers 0–9 We then use a random number, in a loop, to point to array elements and append each character as we build each line A while loop is used to create 12,800 lines per Michael Chapter ■ c02.tex V4 - 03/24/2008 4:48pm Page 69 24 Ways to Process a File Line-by-Line MB the user specifies To create a MB random character file, you need only add the number of MB as a parameter to the shell script name Using the shell script in Listing 2-1, you create a MB, 12,800-line file, with the following syntax: # random_file.Bash The full shell script is shown in Listing 2-1 #!/bin/Bash # # SCRIPT: random_file.Bash # AUTHOR: Randy Michael # DATE: 8/3/2007 # REV: 1.0 # PLATFORM: Not Platform Dependent # # PURPOSE: This script is used to create a # specific size file of random characters # The methods used in this script include # loading an array with alphanumeric # characters, then using the /dev/random # character special file to seed the RANDOM # shell variable, which in turn is used to # extract a random set of characters from the # KEYS array to build the OUTFILE of a # specified MB size # # set -x # Uncomment to debug this script # # set -n # Uncomment to check script syntax # # without any execution Do not forget # # to put the comment back in or the # # script will never execute # ########################################## # DEFINE FILES AND VARIABLES HERE ########################################## typeset -i MB_SIZE=$1 typeset -i RN typeset -i i=1 typeset -i X=0 OUTFILE=largefile.random.txt >$OUTFILE THIS_SCRIPT=$(basename $0) CHAR_FILE=${WORKDIR}/char_file.txt Listing 2-1 random_file.Bash shell script 69 Michael 70 Part I ■ The Basics of Shell Scripting ########################################## # DEFINE FUNCTIONS HERE ########################################## build_random_line () { # This function extracts random characters # from the KEYS array by using the RANDOM # shell variable C=1 LINE= until (( C > 79 )) LINE="${LINE}${KEYS[$(($RANDOM % X + 1))]}" (( C = C + )) done # Return the line of random characters echo "$LINE" } ########################################## elasped_time () { SEC=$1 (( SEC < 60 )) && $SEC seconds]\c" echo -e "[Elasped time: \ (( SEC >= 60 && SEC < 3600 )) && echo -e \ "[Elasped time: $(( SEC / 60 )) $(( SEC % 60 )) sec]\c" (( SEC > 3600 )) && echo -e "[Elasped time: \ $(( SEC / 3600 )) hr $(( (SEC % 3600) / 60 )) \ $(( (SEC % 3600) % 60 )) sec]\c" } ########################################## load_default_keyboard () { # Loop through each character in the following list and # append each character to the $CHAR_FILE file This # produces a file with one character on each line for CHAR in q w e r t y u i o \ Listing 2-1 (continued) c02.tex V4 - 03/24/2008 4:48pm Page 70 Michael Chapter ■ c02.tex V4 - 03/24/2008 4:48pm Page 71 24 Ways to Process a File Line-by-Line p a s d f g h j k l z x c v b n m \ Q W E R T Y U I O P A S D F G H J K L \ Z X C V B N M echo "$CHAR" >> $CHAR_FILE done } ########################################## usage () { echo -e "\nUSAGE: $THIS_SCRIPT Mb_size" echo -e "Where Mb_size is the size of the file to build\n" } ########################################## # BEGINNING OF MAIN ########################################## if (( $# != )) then usage exit fi # Test for an integer value case $MB_SIZE in [0-9]) : # Do nothing ;; *) usage ;; esac # Test for the $CHAR_FILE if [ ! -s "$CHAR_FILE" ] then echo -e "\nNOTE: $CHAR_FILE does not esist" echo "Loading default keyboard data." echo -e "Creating $CHAR_FILE \c" load_default_keyboard echo "Done" fi # Load Character Array echo -e "\nLoading array with alphanumeric character elements" Listing 2-1 (continued) 71 Michael 72 Part I ■ c02.tex V4 - 03/24/2008 4:48pm Page 72 The Basics of Shell Scripting while read ARRAY_ELEMENT (( X = X + )) KEYS[$X]=$ARRAY_ELEMENT done < $CHAR_FILE echo "Total Array Character Elements: $X" # Use /dev/random to seed the shell variable RANDOM echo "Querying the kernel random number generator for a random seed" RN=$(dd if=/dev/random count=1 2>/dev/null \ | od -t u4 | awk ’{print $2}’| head -n 1) # The shell variable RANDOM is limited to 32767 echo "Reducing the random seed value to between and 32767" RN=$(( RN % 32767 + )) # Initialize RANDOM with a new seed echo "Assigning a new seed to the RANDOM shell variable" RANDOM=$RN echo "Building a $MB_SIZE MB random character file ==> $OUTFILE" echo "Please be patient; this may take some time to complete " echo -e "Executing: \c" # Reset the shell SECONDS variable to zero seconds SECONDS=0 TOT_LINES=$(( MB_SIZE * 12800 )) until (( i > TOT_LINES )) build_random_line >> $OUTFILE (( $(( i % 100 )) == )) && echo -e ".\c" (( i = i + )) done # Capture the total seconds Listing 2-1 (continued) [...]... 03/24/2008 4:38pm Page xi Contents Acknowledgments Introduction Part One Chapter 1 xxv xxvii The Basics of Shell Scripting Scripting Quick Start and Review Case Sensitivity UNIX Special Characters Shells Shell Scripts Functions Running a Shell Script Declare the Shell in the Shell Script Comments and Style in Shell Scripts Control Structures if then statement if then else statement if then elif... # $ ? & * ( ) [ ] ‘ ’ " + - ! ^ = | < > Shells A shell is an environment in which we can run our commands, programs, and shell scripts There are different flavors of shells, just as there are different flavors of operating systems Each flavor of shell has its own set of recognized commands and functions This book works with the Bourne, Bash, and Korn shells Shells are located in either the /usr/bin/... Case Sensitivity UNIX is case sensitive Because UNIX is case sensitive, our shell scripts are also case sensitive UNIX Special Characters All of the following characters have a special meaning or function If they are used in a way that their special meaning is not needed, they must be escaped To escape, 3 Michael 4 Part I ■ c01.tex V4 - 03/24/2008 4:45pm Page 4 The Basics of Shell Scripting or remove... the book The shell scripts presented in this book are complete shell scripts, which is one of the things that sets this book apart from other shell- scripting books on the market The solutions are explained thoroughly, with each part of the shell scripts explained in minute detail down to the philosophy and mindset of the author How This Book Is Organized Each chapter starts with a typical UNIX challenge... HP-UX Linux OpenBSD Solaris What Is the Common Denominator? Scripting the Solutions Using uptime to Measure the System Load Scripting with the uptime Command Using sar to Measure the System Load Scripting with the sar Command Using iostat to Measure the System Load Scripting with the iostat Command Using vmstat to Measure the System Load Scripting with the vmstat Command Other Options to Consider Try... go further to build options into the shell script to give the end user more flexibility on the command line When a shell script has to be rewritten for each operating system, a combined shell script is shown at the end of the chapter that will run on all the UNIX flavors studied in this book, except where noted To do this last step, we query the system for the UNIX flavor using the uname command By... technique to solve a challenge in UNIX All the shell scripts in this book are real-world examples of how to solve a problem Thumb through the chapters, and you can see that we tried to hit most of the common (and some uncommon!) tasks in UNIX All the shell scripts have a good explanation of the thinking process, and we always start out with the correct command syntax for the shell script targeting a specific... querying me for UNIX details on almost a weekly basis, I doubt the first edition of this book would have ever been written I especially want to thank Jack Renfro at Chrysler Corporation for giving me my first shell scripting project so long ago I had to start with the man pages, but that is how I learned to dig deep to get the answer Since then I have been on a mission to automate, through shell scripting, ... in our shell scripts and demonstrate the benefits of functions over a shell script written without functions This book is intended for any flavor of UNIX, but it emphasizes the AIX, HP-UX, Linux, OpenBSD, and Solaris operating systems Almost every script in the book is also included on the book’s companion web site (www.wiley.com/go/michael2e) Many of the shell scripts are rewritten for various UNIX. .. the /usr/bin/ directory or the /bin/ directory, depending on the UNIX flavor and specific version Table 1-1 SHELL DIRECTORY Bourne /bin/sh or /usr/bin/sh Bash /bin/Bash or /usr/bin/Bash Korn /bin/ksh or /usr/bin/ksh Shell Scripts The basic concept of a shell script is a list of commands, which are listed in the order of execution A good shell script will have comments, preceded by a pound sign or hash