SHELLdorado Newsletter 3/2000 - September 24, 2000
================================================================
The "SHELLdorado Newsletter" covers UNIX shell script related
topics. To subscribe to this newsletter, leave your e-mail
address at the SHELLdorado homepage:
http://www.shelldorado.com/
"Heiner's SHELLdorado" is a place for UNIX shell script
programmers providing
Many shell script examples,
shell scripting tips & tricks + more...
================================================================
Contents
o What's new at the SHELLdorado?
o Shell Tip: Easy interactive menus with "select"
o Shell Tip: How to execute a command in all subdirectories
o Shell Tip: How to set a "timeout" for commands
-----------------------------------------------------------------
>> What's new at the SHELLdorado?
-----------------------------------------------------------------
o The "SHELLdorado Links" section, one of the most popular
pages of the SHELLdorado, has been revised. Despite the
similar look, behind the scenes everything has changed ;-)
- The link page is now generated from link information
stored in a mySQL database. This provides us with the
opportunity of automated link checking, and subsequent
less "broken" links
- All links have been re-visited, ranked and verified
- The entries have a consistent layout to simplify reading
and browsing
The page address is:
http://www.shelldorado.com/links/
Expect the section to grow considerably, soon!
Thanks to Brian Hiles <brian_hiles@rocketmail.com> for his
valuable comments on the first revisions of the page.
-----------------------------------------------------------------
>> Shell Tip: Easy interactive menus with "select"
-----------------------------------------------------------------
The KornShell and BASH have a very useful (but hardly known)
feature for writing easy interactive menus: the "select"
loop.
If we i.e. would like to have the user remove one file
from the current directory interactively, we could use the
following commands:
PS3='Remove file: ' # Prompt string
select file in *
do
echo "$file" # or: rm -f "$file"
break # only remove one file
done
This would print a selection menu like the following:
1) file1.txt 3) file3.txt 5) selex
2) file2.txt 4) file4.txt 6) tcpconn
Remove file: _
The script user just has to enter the number of the file.
-----------------------------------------------------------------
>> Shell Tip: How to execute a command in all subdirectories
-----------------------------------------------------------------
With the large numbers of directories on a typical UNIX
system, it can be very tedious to run a command in each
of them.
If we i.e. would like to remove all files named *.bak in
all subdirectories, we would have to build a rather long
"find" command line, i.e.
find . -name '*.bak' -print -exec rm -f {}
How easy the same could be if we only had a command that
would carry out a command recursively (i.e. named "global"),
in a way that
global rm -f "*.bak"
would suffice to remove the files in all subdirectories!
The following script code does exactly this:
# global - execute command in all subdirectories
exec 3<&0 # save standard input
find . -type d -print | # print all directory names
while read dirname
do
(cd $dirname
exec 0<&3 # restore standard input
"$@" # run command
)
done
exec 3<&- # close file descriptor
The rather cryptical "exec" lines ensure, that the command
executed in each directory has the terminal at standard input
(and not the directory list generated with "find").
A full-featured script of the same name is available in
the SHELLdorado "Scripts" section:
http://www.shelldorado.com/scripts/cmds/global
-----------------------------------------------------------------
>> Shell Tip: How to set a "timeout" for commands
-----------------------------------------------------------------
Sometimes it is desirable to set a "timeout" for a command.
If it does not complete within a certain period of time, it
should be terminated automatically, and the script should
continue.
The following example shows how to terminate a program
("ping 127.0.0.1") automatically if it does not finish
execution within five seconds:
timeout=5 # in seconds
ping 127.0.0.1 & cmdpid=$! # Command to terminate
# Start "watchdog" process to terminate the command
# after $timeout seconds:
(sleep $timeout; kill -9 $cmdpid) &
watchdogpid=$!
wait $cmdpid # wait for command
kill $watchdogpid >/dev/null 2>&1
The example script starts a "timed" command in the background
("ping 127.0.0.1"), and then starts another background
process (the "watchdog") that will terminate the command
in 5 seconds.
It then waits for the "ping" command to terminate. If it
terminates in time, the "watchdog" is terminated immediately,
and the script continues.
If the command does not terminate in time, the "watchdog"
process will "kill" it after the timeout period, and the
script will continue. The subsequent termination of the
"watchdog" will not be necessary (but will do no harm,
either).
A more generic "timeout" script to monitor any arbitrary
programs is available at the SHELLdorado "Scripts" section:
http://www.shelldorado.com/scripts/cmds/timeout
----------------------------------------------------------------
If you want to comment on the newsletter, or even want to submit
an article of your own, send a mail to
mailto:heiner.steven@shelldorado.com
================================================================
To unsubscribe send a mail with the body "unsubscribe" to
newsletter@shelldorado.com
================================================================