From 03ddc10f2db92f3ff1bad731712a18cc6c836889 Mon Sep 17 00:00:00 2001 From: gferg <> Date: Mon, 6 Jan 2003 21:25:36 +0000 Subject: [PATCH] updated --- LDP/guide/docbook/abs-guide/Change.log | 53 ++++ LDP/guide/docbook/abs-guide/abs-guide.sgml | 230 +++++++++++++++--- LDP/guide/docbook/abs-guide/alias.sh | 11 +- LDP/guide/docbook/abs-guide/escaped.sh | 3 +- LDP/guide/docbook/abs-guide/ex17.sh | 4 + LDP/guide/docbook/abs-guide/ex65.sh | 1 - .../docbook/abs-guide/file-comparison.sh | 3 + LDP/guide/docbook/abs-guide/read-redir.sh | 17 ++ 8 files changed, 275 insertions(+), 47 deletions(-) diff --git a/LDP/guide/docbook/abs-guide/Change.log b/LDP/guide/docbook/abs-guide/Change.log index d3b52825..42775ccd 100644 --- a/LDP/guide/docbook/abs-guide/Change.log +++ b/LDP/guide/docbook/abs-guide/Change.log @@ -3,6 +3,59 @@ RELEASE HISTORY Change log +Version 1.7 (minor update) +'COCONUT' release +01/05/03 + +1) In "Special Variable Types" section of "Introduction to Variables and + Parameters" chapter: + Added note about "$*" and "$@" special variables, and updated "ex17.sh" + example to reflect this. + +2) In "Manipulating Strings" subsection of "Variables Revisited" chapter: + Added "paragraph-space.sh" example. + +3) In "Loop Control" section of "Loops and Branches" chapter: + Added "continue-n.example" to illustrate use of "continue N" construct. + (Thank you, Albert Reiner.) + +4) In "Internal Commands" chapter: + Added section to "read-redir.sh" example to show setting "$IFS" within a + loop. (Thanks, Dim Segebart.) + Added Rory Winston's example of "eval" usage. + +5) In "List Constructs" chapter: + Deleted erroneous comment in "ex65.sh." + (Thank you, Francisco de Jesus Orozco Ruiz.) + +6) In "File Test" section of "Tests" chapter: + Added "broken-link.sh" example. + +7) In "Internal Variables" section of "Variables Revisited" chapter: + Added comment on $PIPESTATUS. + +8) In "RANDOM" section of "Variables Revisited" chapter: + Added the 'jipe' techniques for generating random numbers within a + specified range. + Added "pick-card.sh" example. Thank you once more, jipe. + +9) In "Miscellaneous Commands" section of "External Commands" Chapter: + Amended discussion of "tee" command. + +10) In "System and Administrative Commands" chapter: + Expanded "ulimit" discussion to include "fork bomb" scenario. + +11) In "Aliases" chapter: + Slightly revised "alias.sh" example. + +12) In "Bibliography" section and as a footnote in "Debugging" chapter: + Added reference to Rocky Bernstein's Bash debugger. + +13) Various minor fixups on example scripts. + + + + Version 1.6 (minor update) 'POMEGRANATE' release 09/29/02 diff --git a/LDP/guide/docbook/abs-guide/abs-guide.sgml b/LDP/guide/docbook/abs-guide/abs-guide.sgml index 3364aa0f..82ceac12 100644 --- a/LDP/guide/docbook/abs-guide/abs-guide.sgml +++ b/LDP/guide/docbook/abs-guide/abs-guide.sgml @@ -264,6 +264,11 @@ Uncomment line below to generate index. + + + + + @@ -284,8 +289,8 @@ Uncomment line below to generate index. - 1.6 - 29 September 2002 + 1.7 + 05 January 2003 @@ -382,6 +387,14 @@ Uncomment line below to generate index. more script added. + + 1.7 + 05 January 2003 + mc + 'COCONUT' release: a couple of bugfixes, more material, one + more script. + + @@ -402,7 +415,7 @@ Uncomment line below to generate index. linkend="bzipref">bzip2-ed tarball including both the SGML source and rendered HTML, may be downloaded from + url="http://personal.riverusers.com/~thegrendel/abs-guide-1.7.tar.bz2"> the author's home site. See the change log for a revision history. @@ -442,7 +455,7 @@ Uncomment line below to generate index. Why Shell Programming? - A working knowledge of shell scripting is essential to everyone + A working knowledge of shell scripting is essential to anyone wishing to become reasonably adept at system administration, even if they do not anticipate ever having to actually write a script. Consider that as a Linux machine boots up, it executes the @@ -532,7 +545,7 @@ Uncomment line below to generate index. If any of the above applies, consider a more powerful scripting - language, perhaps Perl, Tcl, Python, or possibly a high-level + language, perhaps Perl, Tcl, Python, Ruby, or possibly a high-level compiled language such as C, C++, or Java. Even then, prototyping the application as a shell script might still be a useful development step. @@ -553,7 +566,7 @@ Uncomment line below to generate index. is not recommended due to certain inherent problems, as pointed out in an October, 1993 Usenet - posting by Tom Christiansen). + post by Tom Christiansen). What follows is a tutorial on shell scripting. It relies @@ -704,8 +717,8 @@ exit $WHATEVER # Doesn't matter. The script will not exit here.#!/bin/sh, the default Bourne Shell in most commercial variants of UNIX, makes the script portable to non-Linux machines, - though you may have to sacrifice a few Bash-specific features - (the script will conform to the + though you may have to sacrifice a few Bash-specific features. + The script will, however, conform to the POSIX Portable Operating @@ -713,36 +726,39 @@ exit $WHATEVER # Doesn't matter. The script will not exit here.Interface, an attempt to standardize UNIX-like OSes. - sh standard). + sh standard. Note that the path given at the sha-bang must - be correct, otherwise an error message, usually Command not - found will be the only result of running the script. + be correct, otherwise an error message -- usually Command + not found -- will be the only result of running the + script. #! can be omitted if the script consists only of a set of generic system commands, using no internal shell directives. The second example, above, requires the initial #!, since the variable assignment line, lines=50, uses a shell-specific construct. - Note that #!/bin/sh invokes the default + Note again that #!/bin/sh invokes the default shell interpreter, which defaults to /bin/bash on a Linux machine. - This tutorial encourages a modular approach + + This tutorial encourages a modular approach to constructing a script. Make note of and collect boilerplate code snippets that might be useful in future scripts. Eventually you can build a quite extensive library of nifty routines. As an example, the following script prolog tests whether the script has been invoked with the correct - number of parameters. + number of parameters. - if [ $# -ne Number_of_expected args ] + if [ $# -ne Number_of_expected args ] then echo "Usage: `basename $0` whatever" exit $WRONG_ARGS fi - + + @@ -755,7 +771,7 @@ fi script may therefore fail to execute. or alternatively bash scriptname. (Not - recommended is using sh <scriptname, + recommended is using sh <scriptname>, since this effectively disables reading from stdin within the script.) Much more convenient is to make the script itself directly executable with @@ -2994,6 +3010,9 @@ arch=$(uname -m) After $9, the arguments must be enclosed in brackets, for example, ${10}, ${11}, ${12}. + The special variables $* and $@ + denote all the positional parameters. + Positional Parameters &ex17; @@ -4252,9 +4271,14 @@ home=/home/bozo + + Testing for broken links + &brokenlink; + + , , , , and illustrate uses of the file test + linkend="mailformat"> also illustrate uses of the file test operators. @@ -5844,7 +5868,8 @@ echo "Last command argument processed = $last_cmd_arg" pipe - Exit status of last executed Exit status of last executed + foreground pipe. Interestingly enough, this does not give the same result as the exit status of the last @@ -5867,6 +5892,36 @@ echo "Last command argument processed = $last_cmd_arg" + + + + The $PIPESTATUS variable + may contain an erroneous 0 value + in a login shell. + + + + +tcsh% bash + +bash$ who | grep nobody | sort +bash$ echo ${PIPESTATUS[*]} +0 + + + + + The above lines contained in a script would produce the expected + 0 1 0 output. + + + + Thank you, Wayne Pollock for pointing this out and supplying the + above example. + + + + @@ -6547,7 +6602,8 @@ echo $_ # : expr - + + stringZ=abcABC123ABCabc echo ${#stringZ} # 15 @@ -6555,10 +6611,16 @@ echo `expr length $stringZ` # 15 echo `expr "$stringZ" : '.*'` # 15 + + + Inserting a blank line between paragraphs in a text file + ¶graphspace; + + Length of Matching Substring at Beginning of String @@ -7600,10 +7662,37 @@ echo "number = $number" # number = 0 &ex21; - Just how random is RANDOM? The best way to test this is + + Picking a random card from a deck + &pickcard; + + + + + + + Jipe points out another set of techniques + for generating random numbers within a range. + + + + # Generate random number between 6 and 30. +rnumber=$((RANDOM%25+6)) + +# Generate random number in the same 6 - 30 range, +#+ but the number must be evenly divisible by 3. +rnumber=$(((RANDOM%30/3+1)*3)) + +# Exercise: Try to figure out the pattern here. + + + + + + Just how random is $RANDOM? The best way to test this is to write a script that tracks the distribution of - random numbers generated by RANDOM. Let's roll - a RANDOM die a few times... + random numbers generated by $RANDOM. Let's roll + a $RANDOM die a few times... Rolling the die with RANDOM @@ -8139,6 +8228,11 @@ echo "number = $number" # number = 0 &continuelevels; + + Using <quote>continue N</quote> in an actual task + &continuenex; + + The continue N construct is difficult to understand and tricky to use in any meaningful context. It is probably best avoided. @@ -8860,6 +8954,17 @@ done &rot14; + Rory Winston contributed the following instance of how + useful eval can be. + + + Using <command>eval</command> to force variable + substitution in a Perl script + &evalex; + + + + The eval command can be risky, and normally should be avoided when there exists a reasonable alternative. An eval @@ -14495,8 +14600,8 @@ LIMIT_STRING [UNIX borrows an idea here from the plumbing trade.] This is a redirection operator, but with a difference. Like the - plumber's tee, it permits siponing - off the output of a command + plumber's tee, it permits siponing + off to a file the output of a command or commands within a pipe, but without affecting the result. This is useful for printing an ongoing process to a file or paper, perhaps to keep track of it for debugging purposes. @@ -17248,16 +17353,45 @@ then ulimit - Sets an upper limit on system - resources. Usually invoked with the - option, which sets a limit on file size (ulimit - -f 1000 limits files to 1 meg maximum). The - option limits the coredump size - (ulimit -c 0 eliminates coredumps). + + Sets an upper limit on use + of system resources. Usually invoked with the + option, which sets a limit on file size + (ulimit -f 1000 limits files to 1 meg + maximum). The option limits the coredump + size (ulimit -c 0 eliminates coredumps). Normally, the value of ulimit would be set in /etc/profile and/or ~/.bash_profile (see ). + + + + Judicious use of ulimit can + protect a system against the dreaded fork + bomb. + + + #!/bin/bash + +while 1 # Endless loop. +do + $0 & # This script invokes itself . . . + #+ forks an infinite number of times . . . + #+ until the system freezes up because all resources exhausted. +done # This is the notorious sorcerer's appentice scenario. + +exit 0 # Will not exit here, because this script will never terminate. + + + A ulimit -Hu XX (where + XX is the user process limit) in + /etc/profile would abort + this script when it exceeds the preset limit. + + + + @@ -20256,9 +20390,10 @@ false && ( true || echo false ) # (nothing echoed) # Thanks, S.C. - See for an illustration of using - an and / or list to test variables. - + See and for illustrations of using an and + / or list to test variables. + @@ -20857,9 +20992,16 @@ ln -s /dev/null ~/.netscape/cookies Debugging The Bash shell contains no debugger, nor even any - debugging-specific commands or constructs. Syntax errors or - outright typos in the script generate cryptic error messages that - are often of no help in debugging a non-functional script. + debugging-specific commands or constructs. + + Rocky Bernstein's + Bash debugger + partially makes up for this lack. + + Syntax errors or outright typos in the script generate cryptic + error messages that are often of no help in debugging a + non-functional script. A buggy script @@ -22946,8 +23088,9 @@ fi were Gabor Kiss, Leopold Toetsch, Peter Tillier, Marcus Berglof, Tony Richardson, Nick Drage (script ideas!), Rich Bartell, Jess Thrysoee, Adam Lazur, Bram Moolenaar, Baris Cicek, Greg Keraunen, - Keith Matthews, Sandro Magi, and David Lawyer (himself an author - of 4 HOWTOs). + Keith Matthews, Sandro Magi, Albert Reiner, Dim Segebart, Rory + Winston, Lee Bigelow, Wayne Pollock, jipe, and + David Lawyer (himself an author of 4 HOWTOs). My gratitude to Chet Ramey and Brian Fox for writing Bash, @@ -23499,6 +23642,15 @@ fi Hohensee has written the osimpa i386 assembler entirely as Bash scripts. + + + + + + Rocky Bernstein is in the process of developing a + full-fledged debugger for + Bash. --- diff --git a/LDP/guide/docbook/abs-guide/alias.sh b/LDP/guide/docbook/abs-guide/alias.sh index c0fa88c5..56008764 100644 --- a/LDP/guide/docbook/abs-guide/alias.sh +++ b/LDP/guide/docbook/abs-guide/alias.sh @@ -55,20 +55,19 @@ do alias rrr="ls -l" echo "Trying aliased \"rrr\" within \"while\" loop:" rrr /usr/X11R6/bin/mk* #* Alias will not expand here either. + # alias.sh: line 57: rrr: command not found let count+=1 done echo; echo -alias xyz="cat $1" # Try a positional parameter in an alias. -xyz # Assumes you invoke the script - #+ with a filename as a parameter. +alias xyz='cat $0' # Script lists itself. + # Note strong quotes. +xyz # This seems to work, #+ although the Bash documentation suggests that it shouldn't. # # However, as Steve Jacobson points out, -#+ the "$1" parameter expands immediately upon declaration of the alias, -#+ so, in the strictest sense, this is not an example -#+ of parameterizing an alias. +#+ the "$0" parameter expands immediately upon declaration of the alias. exit 0 diff --git a/LDP/guide/docbook/abs-guide/escaped.sh b/LDP/guide/docbook/abs-guide/escaped.sh index 6aa08d39..f8c764f0 100644 --- a/LDP/guide/docbook/abs-guide/escaped.sh +++ b/LDP/guide/docbook/abs-guide/escaped.sh @@ -26,8 +26,9 @@ echo "QUOTATION MARKS" echo $'\t \042 \t' # Quote (") framed by tabs. # It also works with hexadecimal values, in an $'\xhhh' construct. -echo $'\t \x022 \t' # Quote (") framed by tabs. +echo $'\t \x22 \t' # Quote (") framed by tabs. # Thank you, Greg Keraunen, for pointing this out. +# Earlier Bash versions allowed '\x022'. echo "===============" echo diff --git a/LDP/guide/docbook/abs-guide/ex17.sh b/LDP/guide/docbook/abs-guide/ex17.sh index e9974b01..157e7971 100644 --- a/LDP/guide/docbook/abs-guide/ex17.sh +++ b/LDP/guide/docbook/abs-guide/ex17.sh @@ -36,8 +36,12 @@ then echo "Parameter #10 is ${10}" fi +echo "-----------------------------------" +echo "All the command-line parameters are: "$*"" + if [ $# -lt "$MINPARAMS" ] then + echo echo "Give me at least $MINPARAMS command-line arguments!" fi diff --git a/LDP/guide/docbook/abs-guide/ex65.sh b/LDP/guide/docbook/abs-guide/ex65.sh index 3447a036..f9c26b30 100644 --- a/LDP/guide/docbook/abs-guide/ex65.sh +++ b/LDP/guide/docbook/abs-guide/ex65.sh @@ -21,7 +21,6 @@ Cowardly refusing to delete a nonexistent file." [ ! -f "$file" ] || (rm -f $file; echo "File \"$file\" deleted.") # OR LIST, to delete file if present. -# ( command1 ; command2 ) is, in effect, an AND LIST variant. # Note logic inversion above. # AND LIST executes on true, OR LIST on false. diff --git a/LDP/guide/docbook/abs-guide/file-comparison.sh b/LDP/guide/docbook/abs-guide/file-comparison.sh index 5b8dfb3d..590bff02 100644 --- a/LDP/guide/docbook/abs-guide/file-comparison.sh +++ b/LDP/guide/docbook/abs-guide/file-comparison.sh @@ -17,6 +17,9 @@ then fi cmp $1 $2 &> /dev/null # /dev/null buries the output of the "cmp" command. +# cmp -s $1 $2 has same result ("-s" silent flag to "cmp") +# Thank you Anders Gustavsson for pointing this out. +# # Also works with 'diff', i.e., diff $1 $2 &> /dev/null if [ $? -eq 0 ] # Test exit status of "cmp" command. diff --git a/LDP/guide/docbook/abs-guide/read-redir.sh b/LDP/guide/docbook/abs-guide/read-redir.sh index e66abedd..d3009a84 100644 --- a/LDP/guide/docbook/abs-guide/read-redir.sh +++ b/LDP/guide/docbook/abs-guide/read-redir.sh @@ -37,4 +37,21 @@ done </etc/passwd # I/O redirection. IFS=$OIFS # Restore originial $IFS. # This code snippet also by Heiner Steven. + + +# Setting the $IFS variable within the loop itself +#+ eliminates the need for storing the original $IFS +#+ in a temporary variable. +# Thanks, Dim Segebart, for pointing this out. +echo "------------------------------------------------" +echo "List of all users:" + +while IFS=: read name passwd uid gid fullname ignore +do + echo "$name ($fullname)" +done </etc/passwd # I/O redirection. + +echo +echo "\$IFS still $IFS" + exit 0