From b3221c8f43a0aa7ef986a8f01be4a407c510ed45 Mon Sep 17 00:00:00 2001 From: tille <> Date: Thu, 28 Sep 2006 09:42:45 +0000 Subject: [PATCH] comments from readers --- .../docbook/Bash-Beginners-Guide/chap1.xml | 2 +- .../docbook/Bash-Beginners-Guide/chap11.xml | 2 +- .../docbook/Bash-Beginners-Guide/chap3.xml | 2 +- .../docbook/Bash-Beginners-Guide/chap4.xml | 9 ++---- .../docbook/Bash-Beginners-Guide/chap6.xml | 2 +- .../docbook/Bash-Beginners-Guide/chap7.xml | 15 +++++++--- .../docbook/Bash-Beginners-Guide/chap8.xml | 28 +++++++++++++++---- .../docbook/Bash-Beginners-Guide/chap9.xml | 18 ++++++++---- .../docbook/Bash-Beginners-Guide/gloss.xml | 19 ------------- 9 files changed, 53 insertions(+), 44 deletions(-) diff --git a/LDP/guide/docbook/Bash-Beginners-Guide/chap1.xml b/LDP/guide/docbook/Bash-Beginners-Guide/chap1.xml index 8da448bd..72164412 100644 --- a/LDP/guide/docbook/Bash-Beginners-Guide/chap1.xml +++ b/LDP/guide/docbook/Bash-Beginners-Guide/chap1.xml @@ -27,7 +27,7 @@ shell, intuitive and flexible. Probably most advisable for beginning users whil of add-ons and plug-ins. This means that the Bourne Again shell is compatible with the Bourne shell: commands that work in sh, also work in bash. However, the reverse is not always the case. All examples and exercises in this book use bash. csh or C shell: the syntax of this shell resembles that of the C programming language. Sometimes asked for by programmers. -tcsh or Turbo C shell: a superset of the common C shell, enhancing user-friendliness and speed. +tcsh or TENEX C shell: a superset of the common C shell, enhancing user-friendliness and speed. That is why some also call it the Turbo C shell. ksh or the Korn shell: sometimes appreciated by people with a UNIX background. A superset of the Bourne shell; with standard configuration a nightmare for beginning users. diff --git a/LDP/guide/docbook/Bash-Beginners-Guide/chap11.xml b/LDP/guide/docbook/Bash-Beginners-Guide/chap11.xml index 0f97a9c3..4dd3fdb3 100644 --- a/LDP/guide/docbook/Bash-Beginners-Guide/chap11.xml +++ b/LDP/guide/docbook/Bash-Beginners-Guide/chap11.xml @@ -70,7 +70,7 @@ The exit code of this function is 0. if [ $RETVAL -eq 0 ]; then <start the daemon> -Or like this example from the /etc/init.d/amd script, where Bash's optimazation features are used: +Or like this example from the /etc/init.d/amd script, where Bash's optimization features are used: [ $RETVAL = 0 ] && touch /var/lock/subsys/amd diff --git a/LDP/guide/docbook/Bash-Beginners-Guide/chap3.xml b/LDP/guide/docbook/Bash-Beginners-Guide/chap3.xml index c3b079db..45978239 100644 --- a/LDP/guide/docbook/Bash-Beginners-Guide/chap3.xml +++ b/LDP/guide/docbook/Bash-Beginners-Guide/chap3.xml @@ -394,7 +394,7 @@ bash: export: `1number=1': not a valid identifier franky ~> MYVAR1="2" -franky ~7gt; echo $MYVAR1 +franky ~> echo $MYVAR1 2 franky ~> first_name="Franky" diff --git a/LDP/guide/docbook/Bash-Beginners-Guide/chap4.xml b/LDP/guide/docbook/Bash-Beginners-Guide/chap4.xml index 0ac16cb0..78aa468f 100644 --- a/LDP/guide/docbook/Bash-Beginners-Guide/chap4.xml +++ b/LDP/guide/docbook/Bash-Beginners-Guide/chap4.xml @@ -138,11 +138,8 @@ floppy:x:19: xfs:x:43: nfsnobody:x:65534: postfix:x:89: - -cathy ~> ls *[1-9].xml -app1.xml chap1.xml chap2.xml chap3.xml chap4.xml -In the example, all the lines containing either a y or f character are first displayed, followed by an example of using a range with the ls command. +In the example, all the lines containing either a y or f character are displayed. Wildcards @@ -169,11 +166,11 @@ cheesecloth cheetah --output omitted-- -If you want to find the literal asterisk character in a file or output, use grep : +If you want to find the literal asterisk character in a file or output, use single quotes. Cathy in the example below first tries finding the asterisk character in /etc/profile without using quotes, which does not return any lines. Using quotes, output is generated: cathy ~> grep * /etc/profile -cathy ~> grep '*' /etc/profile +cathy ~> grep '*' /etc/profile for i in /etc/profile.d/*.sh ; do diff --git a/LDP/guide/docbook/Bash-Beginners-Guide/chap6.xml b/LDP/guide/docbook/Bash-Beginners-Guide/chap6.xml index 08de5c29..b6310ca4 100644 --- a/LDP/guide/docbook/Bash-Beginners-Guide/chap6.xml +++ b/LDP/guide/docbook/Bash-Beginners-Guide/chap6.xml @@ -344,7 +344,7 @@ END { print "</pre>\n</body>\n</html>" } On-the-fly variable declaration is straightforward and allows for simple calculation of sums, statistics and other operations on the processed input stream. Variables and commands can be put in awk scripts for background processing. Other things you should know about awk: -The language remains well-known on UNIX and alikes, but for executing similar tasks, Perl is now more commonly used. However, awk has a much steeper learning curve. In other words, Perl is more difficult to learn. +The language remains well-known on UNIX and alikes, but for executing similar tasks, Perl is now more commonly used. However, awk has a much steeper learning curve (meaning that you learn a lot in a very short time). In other words, Perl is more difficult to learn. Both Perl and awk share the reputation of being incomprehensible, even to the actual authors of the programs that use these languages. So document your code! diff --git a/LDP/guide/docbook/Bash-Beginners-Guide/chap7.xml b/LDP/guide/docbook/Bash-Beginners-Guide/chap7.xml index 131b5ca4..00a71b27 100644 --- a/LDP/guide/docbook/Bash-Beginners-Guide/chap7.xml +++ b/LDP/guide/docbook/Bash-Beginners-Guide/chap7.xml @@ -197,7 +197,7 @@ WEEKOFFSET=$[ $(date +"%V") % 2 ] if [ $WEEKOFFSET -eq "0" ]; then echo "Sunday evening, put out the garbage cans." | mail -s "Garbage cans out" your@your_domain.org - +fi @@ -253,6 +253,9 @@ How come the lady hasn't got a drink yet? freddy scripts> +[] vs. [[]] +Contrary to [, [[ prevents word splitting of variable values. So, if VAR="var with spaces", you do not need to double quote $VAR in a test - eventhough using quotes remains a good habit. Also, [[ prevents pathname expansion, so literal strings with wildcards do not try to expand to filenames. Using [[, == and != interpret strings to the right as shell glob patterns to be matched against the value to the left, for instance: [[ "value" == val* ]]. + Like the CONSEQUENT-COMMANDS list following the then statement, the ALTERNATE-CONSEQUENT-COMMANDS list following the else statement can hold any UNIX-style command that returns an exit status. Another example, extending the one from : @@ -289,7 +292,7 @@ your account is managed from the local /etc/passwd file #!/bin/bash # This script prints a message about your weight if you give it your -# weight in kilos and hight in centimeters. +# weight in kilos and height in centimeters. weight="$1" height="$2" @@ -317,7 +320,7 @@ You should eat a bit more fat. #!/bin/bash # This script prints a message about your weight if you give it your -# weight in kilos and hight in centimeters. +# weight in kilos and height in centimeters. if [ ! $# == 2 ]; then echo "Usage: $0 weight_in_kilos length_in_centimeters" @@ -365,6 +368,9 @@ else fi Note that the file is referred to using a variable; in this case it is the first argument to the script. Alternatively, when no arguments are given, file locations are usually stored in variables at the beginning of a script, and their content is referred to using these variables. Thus, when you want to change a file name in a script, you only need to do it once. +Filenames with spaces +The above example will fail if the value of $1 can be parsed as multiple words. In that case, the if command can be fixed either using double quotes around the filename, or by using [[ instead of [. + if/then/elif/else constructs @@ -547,7 +553,7 @@ case $space in Message="I'm drowning here! There's a partition at $space %!" ;; *) - Message="I seem to be running with an nonexitent amount of disk space..." + Message="I seem to be running with an nonexistent amount of disk space..." ;; esac @@ -630,6 +636,7 @@ esac Edit the leaptest.sh script from so that it requires one argument, the year. Test that exactly one argument is supplied. Write a script called whichdaemon.sh that checks if the httpd and init daemons are running on your system. If an httpd is running, the script should print a message like, This machine is running a web server. Use ps to check on processes. Write a script that makes a backup of your home directory on a remote machine using scp. The script should report in a log file, for instance ~/log/homebackup.log. If you don't have a second machine to copy the backup to, use scp to test copying it to the localhost. This requires SSH keys between the two hosts, or else you have to supply a password. The creation of SSH keys is explained in man ssh-keygen. +Adapt the script from the first example in to include the case of exactly 90% disk space usage, and lower than 10% disk space usage. The script should use tar for the creation of the backup and gzip or bzip2 for compressing the .tar file. Put all filenames in variables. Put the name of the remote server and the remote directory in a variable. This will make it easier to re-use the script or to make changes to it in the future. The script should check for the existence of a compressed archive. If this exists, remove it first in order to prevent output generation. The script should also check for available diskspace. Keep in mind that at any given moment you could have the data in your home directory, the data in the .tar file and the data in the compressed archive all together on your disk. If there is not enough diskspace, exit with an error message in the log file. diff --git a/LDP/guide/docbook/Bash-Beginners-Guide/chap8.xml b/LDP/guide/docbook/Bash-Beginners-Guide/chap8.xml index fcb74f04..33706ffb 100644 --- a/LDP/guide/docbook/Bash-Beginners-Guide/chap8.xml +++ b/LDP/guide/docbook/Bash-Beginners-Guide/chap8.xml @@ -296,7 +296,18 @@ lrwx------ 1 michel michel 64 Jan 23 12:11 /proc/self/fd/0 -> /dev/pts/6 lrwx------ 1 michel michel 64 Jan 23 12:11 /proc/self/fd/1 -> /dev/pts/6 lrwx------ 1 michel michel 64 Jan 23 12:11 /proc/self/fd/2 -> /dev/pts/6 +Note that each process has its own view of the files under /proc/self, as it is actually a symbolic link to /proc/<process_ID>. You might want to check info MAKEDEV and info proc for more information about /proc subdirectories and the way your system handles standard file descriptors for each running process. +When excuting a given command, the following steps are excuted, in order: + +If the standard output of a previous command is being piped to the standard input of the current command, then /proc/<current_process_ID>/fd/0 is updated to target the same anonymous pipe as /proc/<previous_process_ID/fd/1. +If the standard output of the current command is being piped to the standard input of the next command, then /proc/<current_process_ID>/fd/1 is updated to target another anonymous pipe. +Redirection for the current command is processed from left to right. +Redirection N>&M or N<&M after a command has the effect of creating or updating the symbolic link /proc/self/fd/N with the same target as the symbolic link /proc/self/fd/M. +The redirections N> file and N< file have the effect of creating or updating the symbolic link /proc/self/fd/N with the target file. +File descriptor closure N>&- has the effect of deleting the symbolic link /proc/self/fd/N. +Only now is the current command executed. + When you run a script from the command line, nothing much changes because the child shell process will use the same file descriptors as the parent. When no such parent is available, for instance when you run a script using the cron facility, the standard file descriptors are pipes or other (temporary) files, unless some form of redirection is used. This is demonstrated in the example below, which shows output from a simple at script: michel ~> date @@ -336,11 +347,11 @@ lr-x------ 1 michel michel 64 Jan 24 11:32 3 -> /proc/21974/fd From the previous examples, it is clear that you can provide input and output files for a script (see for more), but some tend to forget about redirecting errors - output which might be depended upon later on. Also, if you are lucky, errors will be mailed to you and eventual causes of failure might get revealed. If you are not as lucky, errors will cause your script to fail and won't be caught or sent anywhere, so that you can't start to do any worthwhile debugging. When redirecting errors, note that the order of precedence is significant. For example, this command, issued in /var/spool -ls * 2 > /var/tmp/unaccessible-in-spool +ls * 2> /var/tmp/unaccessible-in-spool -will redirect output of the ls command to the file unaccessible-in-spool in /var/tmp. The command +will redirect standard output of the ls command to the file unaccessible-in-spool in /var/tmp. The command -ls * > /var/tmp/spoollist 2 >& 1 +ls * > /var/tmp/spoollist 2>&1 will direct both standard input and standard error to the file spoollist. The command @@ -374,13 +385,13 @@ This text is printed at the end of each print job. Read and exec Assigning file descriptors to files -Another way of looking at file descriptors is thinking of them as a way to assign a numeric value to a file. Instead of using the file name, you can use the file descriptor number. The exec built-in command is used to assign a file descriptor to a file. Use +Another way of looking at file descriptors is thinking of them as a way to assign a numeric value to a file. Instead of using the file name, you can use the file descriptor number. The exec built-in command can be used to replace the shell of the current process or to alter the file descriptors of the current shell. For example, it can be used to assign a file descriptor to a file. Use exec fdN> file for assigning file descriptor N to file for output, and exec fdN< file for assigning file descriptor N to file for input. After a file descriptor has been assigned to a file, it can be used with the shell redirection operators, as is demonstrated in the following example: -michel ~> exec 4 > result.txt +michel ~> exec 4> result.txt michel ~> filter body.txt | cat header.txt /dev/fd/0 footer.txt >& 4 @@ -410,8 +421,10 @@ rm "$CONFIG" 2>/dev/null echo "Output will be saved in $CONFIG." +# create fd 7 with same target as fd 0 (save stdin "value") exec 7<&0 +# update fd 0 to target file /etc/passwd exec < /etc/passwd # Read the first line of /etc/passwd @@ -421,6 +434,7 @@ echo "Saving root account info..." echo "Your root account info:" >> "$CONFIG" echo $rootpasswd >> "$CONFIG" +# update fd 0 to target fd 7 target (old fd 0 target); delete fd 7 exec 0<&7 7<&- echo -n "Enter comment or [ENTER] for no comment: " @@ -481,13 +495,17 @@ in central DNS INPUTDIR="$1" +# fd 6 targets fd 1 target (console out) in current shell exec 6>&1 +# fd 1 targets pipe, fd 2 targets fd 1 target (pipe), +# fd 1 targets fd 6 target (console out), fd 6 closed, execute ls ls "$INPUTDIR"/* 2>&1 >&6 6>&- \ # Closes fd 6 for awk, but not for ls. | awk 'BEGIN { FS=":" } { print "YOU HAVE NO ACCESS TO" $2 }' 6>&- +# fd 6 closed for current shell exec 6>&- diff --git a/LDP/guide/docbook/Bash-Beginners-Guide/chap9.xml b/LDP/guide/docbook/Bash-Beginners-Guide/chap9.xml index a9474fdc..ddb5c2d1 100644 --- a/LDP/guide/docbook/Bash-Beginners-Guide/chap9.xml +++ b/LDP/guide/docbook/Bash-Beginners-Guide/chap9.xml @@ -53,6 +53,9 @@ for i in "$LIST"; do done Since we don't do a line count here, there is no way of knowing the line number from which to start deleting lines until reaching the end. The problem is solved using tac, which reverses the lines in a file. +The basename command +Instead of using sed to replace the html suffix with php, it would be cleaner to use the basename command. Read the man page for more info. + @@ -248,7 +251,7 @@ done -I/0 redirection and loops +I/O redirection and loops Input redirection Instead of controlling a loop by testing the result of a command or by user input, you can specify a file from which to read input that controls the loop. In such cases, read is often the controlling command. As long as input lines are fed into the loop, execution of the loop commands continues. As soon as all the input lines are read the loop exits. Since the loop construct is considered to be one command structure (such as while TEST-COMMAND; do CONSEQUENT-COMMANDS; done), the redirection should occur after the done statement, so that it complies with the form @@ -269,9 +272,12 @@ done ARCHIVENR=`date +%Y%m%d` DESTDIR="$PWD/archive-$ARCHIVENR" -mkdir $DESTDIR +mkdir "$DESTDIR" + +# using quotes to catch file names containing spaces, using read -d for more +# fool-proof usage: +find "$PWD" -type f -a -mtime +5 | while read -d $'\000' file -find $PWD -type f -a -mtime +5 | while read file do gzip "$file"; mv "$file".gz "$DESTDIR" echo "$file archived" @@ -513,10 +519,10 @@ fi while (( "$#" )); do -if [[ "$(ls $1)" == "" ]]; then +if [[ $(ls "$1") == "" ]]; then echo "Empty directory, nothing to be done." else - find $1 -type f -a -atime +365 -exec rm -i {} \; + find "$1" -type f -a -atime +365 -exec rm -i {} \; fi shift @@ -536,7 +542,7 @@ if [ $# -lt 1 ]; then exit 1 fi while (($#)); do - yum install $1 << CONFIRM + yum install "$1" << CONFIRM y CONFIRM shift diff --git a/LDP/guide/docbook/Bash-Beginners-Guide/gloss.xml b/LDP/guide/docbook/Bash-Beginners-Guide/gloss.xml index b148036b..6131774f 100644 --- a/LDP/guide/docbook/Bash-Beginners-Guide/gloss.xml +++ b/LDP/guide/docbook/Bash-Beginners-Guide/gloss.xml @@ -439,12 +439,6 @@ Print lines matching a pattern. - - groff - - Emulate nroff command with groff. - - grub @@ -1011,12 +1005,6 @@ - - roff - - A survey of the roff typesetting system. - - rpm @@ -1231,13 +1219,6 @@ - - troff - - Format documents. - - - twm