- •Advanced Bash-Scripting Guide
- •Dedication
- •Table of Contents
- •Part 1. Introduction
- •Advanced Bash-Scripting Guide
- •Chapter 2. Starting Off With a Sha-Bang
- •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
- •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.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
- •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
- •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
- •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. Security Issues
- •34.8. Portability Issues
- •34.9. Shell Scripting Under Windows
- •Chapter 35. Bash, version 2
- •36. Endnotes
- •36.1. Author's Note
- •36.2. About the Author
- •36.3. Tools Used to Produce This Book
- •36.4. Credits
- •List of Tables
- •List of Examples
- •Bibliography
Invoking the script
|
Advanced Bash-Scripting Guide: |
|
Prev |
Chapter 2. Starting Off With a Sha-Bang |
Next |
2.1. Invoking the script
Having written the script, you can invoke it by sh scriptname, [1] or alternatively bash scriptname. (Not 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 a chmod.
Either:
chmod 555 scriptname (gives everyone read/execute permission) [2]
or
chmod +rx scriptname (gives everyone read/execute permission)
chmod u+rx scriptname (gives only the script owner read/execute permission)
Having made the script executable, you may now test it by ./scriptname. [3] If it begins with a "sha-bang" line, invoking the script calls the correct command interpreter to run it.
As a final step, after testing and debugging, you would likely want to move it to /usr/local/bin (as root, of course), to make the script available to yourself and all other users as a system-wide executable. The script could then be invoked by simply typing scriptname [ENTER] from the command line.
Notes
[1]Caution: invoking a Bash script by sh scriptname turns off Bash-specific extensions, and the script may therefore fail to execute.
[2]A script needs read, as well as execute permission for it to run, since the shell needs to be able to read it.
http://tldp.org/LDP/abs/html/invoking.html (1 of 2) [7/15/2002 6:35:30 PM]
Invoking the script
[3]Why not simply invoke the script with scriptname? If the directory you are in ($PWD) is where scriptname is located, why doesn't this work? This fails because, for security reasons, the current directory, "." is not included in a user's $PATH. It is therefore necessary to explicitly invoke the script in the current directory with a
./scriptname.
Prev |
Home |
Next |
Starting Off With a Sha-Bang |
Up |
Preliminary Exercises |
http://tldp.org/LDP/abs/html/invoking.html (2 of 2) [7/15/2002 6:35:30 PM]
Portability Issues
|
Advanced Bash-Scripting Guide: |
|
Prev |
Chapter 34. Miscellany |
Next |
34.8. Portability Issues
This book deals specifically with Bash scripting on a GNU/Linux system. All the same, users of sh and ksh will find much of value here.
As it happens, many of the various shells and scripting languages seem to be converging toward the POSIX 1003.2 standard. Invoking Bash with the --posix option or inserting a set -o posix at the head of a script causes Bash to conform very closely to this standard. Even lacking this measure, most Bash scripts will run as-is under ksh, and vice-versa, since Chet Ramey has been busily porting ksh features to the latest versions of Bash.
On a commercial UNIX machine, scripts using GNU-specific features of standard commands may not work. This has become less of a problem in the last few years, as the GNU utilities have pretty much displaced their proprietary counterparts even on "big-iron" UNIX. Caldera's recent release of the source to many of the original UNIX utilities will only accelerate the trend.
Prev |
Home |
Next |
Security Issues |
Up |
Shell Scripting Under |
|
|
Windows |
http://tldp.org/LDP/abs/html/portabilityissues.html [7/15/2002 6:35:31 PM]
Optimizations
|
Advanced Bash-Scripting Guide: |
|
Prev |
Chapter 34. Miscellany |
Next |
34.4. Optimizations
Most shell scripts are quick 'n dirty solutions to non-complex problems. As such, optimizing them for speed is not much of an issue. Consider the case, though, where a script carries out an important task, does it well, but runs too slowly. Rewriting it in a compiled language may not be a palatable option. The simplest fix would be to rewrite the parts of the script that slow it down. Is it possible to apply principles of code optimization even to a lowly shell script?
Check the loops in the script. Time consumed by repetitive operations adds up quickly. If at all possible, remove time-consuming operations from within loops.
Use builtin commands in preference to system commands. Builtins execute faster and usually do not launch a subshell when invoked.
Use the time and times tools to profile computation-intensive commands. Consider rewriting time-critical code sections in C, or even in assembler.
Try to minimize file I/O. Bash is not particularly efficient at handling files, so consider using more appropriate tools for this within the script, such as awk or Perl.
Write your scripts in a structured, coherent form, so they can be reorganized and tightened up as necessary. Some of the optimization techniques applicable to high-level languages may work for scripts, but others, such as loop unrolling, are mostly irrelevant. Above all, use common sense.
For an excellent demonstration of how optimization can drastically reduce the execution time of a script, see Example 12-32.
Prev |
Home |
Next |
Tests and Comparisons: |
Up |
Assorted Tips |
Alternatives |
|
|
http://tldp.org/LDP/abs/html/optimizations.html [7/15/2002 6:35:31 PM]
Unofficial Shell Scripting Stylesheet
|
Advanced Bash-Scripting Guide: |
|
Prev |
Chapter 33. Scripting With Style |
Next |
33.1. Unofficial Shell Scripting Stylesheet
●Comment your code. This makes it easier for others to understand (and appreciate), and easier for you to maintain.
PASS="$PASS${MATRIX:$(($RANDOM%${#MATRIX})):1}"
#It made perfect sense when you wrote it last year, but now it's a complete mystery.
#(From Antek Sawicki's "pw.sh" script.)
Add descriptive headers to your scripts and functions.
#!/bin/bash
#************************************************#
# xyz.sh
#written by Bozo Bozeman
# |
July 05, 2001 |
# |
Clean up project files. |
#************************************************# |
|
BADDIR=65 |
# No such directory. |
projectdir=/home/bozo/projects |
# Directory to clean up. |
#------------------------------------------------------- |
# |
#cleanup_pfiles ()
#Removes all files in designated directory.
#Parameter: $target_directory
#Returns: 0 on success, $BADDIR if something went wrong.
#------------------------------------------------------- |
# |
cleanup_pfiles () |
|
{ |
|
if [ ! -d "$1" ] |
# Test if target directory exists. |
then |
|
echo "$1 is not a directory." return $BADDIR
fi
rm -f "$1"/*
return 0 # Success.
}
cleanup_pfiles $projectdir
exit 0
Be sure to put the #!/bin/bash at the beginning of the first line of the script, preceding any comment headers.
●Avoid using "magic numbers", [1] that is, "hard-wired" literal constants. Use meaningful variable names instead. This makes the script easier to understand and permits making changes and updates without breaking the application.
http://tldp.org/LDP/abs/html/unofficialst.html (1 of 3) [7/15/2002 6:35:32 PM]
Unofficial Shell Scripting Stylesheet
if [ -f /var/log/messages ] then
...
fi
#A year later, you decide to change the script to check /var/log/syslog.
#It is now necessary to manually change the script, instance by instance,
#and hope nothing breaks.
#A better way:
LOGFILE=/var/log/messages # Only line that needs to be changed. if [ -f "$LOGFILE" ]
then
...
fi
● Choose descriptive names for variables and functions.
fl=`ls -al $dirname` |
# Cryptic. |
file_listing=`ls -al $dirname` |
# Better. |
MAXVAL=10 # All caps used for a script constant. |
|
while [ "$index" -le "$MAXVAL" ] |
|
... |
|
E_NOTFOUND=75 |
# Uppercase for an errorcode, |
|
# and name begins with "E_". |
if [ ! -e "$filename" ] |
|
then |
|
echo "File $filename not found." |
|
exit $E_NOTFOUND |
|
fi |
|
MAIL_DIRECTORY=/var/spool/mail/bozo |
# Uppercase for an environmental variable. |
export MAIL_DIRECTORY |
|
GetAnswer () |
# Mixed case works well for a function. |
{ |
|
prompt=$1
echo -n $prompt read answer return $answer
}
GetAnswer "What is your favorite number? " favorite_number=$?
echo $favorite_number
_uservariable=23 |
# Permissable, but not recommended. |
#It's better for user-defined variables not to start with an underscore.
#Leave that for system variables.
●Use exit codes in a systematic and meaningful way.
http://tldp.org/LDP/abs/html/unofficialst.html (2 of 3) [7/15/2002 6:35:32 PM]
Unofficial Shell Scripting Stylesheet
E_WRONG_ARGS=65
...
...
exit $E_WRONG_ARGS
See also Appendix C.
●Break complex scripts into simpler modules. Use functions where appropriate. See Example 35-4.
●Don't use a complex construct where a simpler one will do.
COMMAND
if [ $? -eq 0 ]
...
# Redundant and non-intuitive.
if COMMAND
...
# More concise (if perhaps not quite as legible).
Notes
[1]In this context, " magic numbers" have an entirely different meaning than the magic numbers used to designate file types.
Prev |
Home |
Next |
Scripting With Style |
Up |
Miscellany |
http://tldp.org/LDP/abs/html/unofficialst.html (3 of 3) [7/15/2002 6:35:32 PM]
Security Issues
|
Advanced Bash-Scripting Guide: |
|
Prev |
Chapter 34. Miscellany |
Next |
34.7. Security Issues
A brief warning about script security is appropriate. A shell script may contain a worm, trojan, or even a virus. For that reason, never run as root a script (or permit it to be inserted into the system startup scripts in /etc/rc.d) unless you have obtained said script from a trusted source or you have carefully analyzed it to make certain it does nothing harmful.
Various researchers at Bell Labs and other sites, including M. Douglas McIlroy, Tom Duff, and Fred Cohen have investigated the implications of shell script viruses. They conclude that it is all to easy for even a novice, a "script kiddie", to write one. [1]
Here is yet another reason to learn scripting. Being able to look at and understand scripts may protect your system from being hacked or damaged.
Notes
[1]See Marius van Oers' article, Unix Shell Scripting Malware, and also the Denning reference in the bibliography.
Prev |
Home |
Next |
Oddities |
Up |
Portability Issues |
http://tldp.org/LDP/abs/html/securityissues.html [7/15/2002 6:35:33 PM]