- •Table of Contents
- •Chapter 1. Why Shell Programming?
- •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
- •Chapter 8. Operations and Related Topics
- •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.2.1. Manipulating strings using awk
- •9.2.2. Further Discussion
- •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
- •11.1. Job Control Commands
- •Chapter 12. External Filters, Programs and Commands
- •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
- •23.2.1. Local variables make recursion possible.
- •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
- •33.1. Unofficial Shell Scripting Stylesheet
- •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. Portability Issues
- •34.8. Shell Scripting Under Windows
- •Chapter 35. Bash, version 2
- •Chapter 36. Endnotes
- •36.1. Author's Note
- •36.2. About the Author
- •36.3. Tools Used to Produce This Book
- •36.3.1. Hardware
- •36.3.2. Software and Printware
- •36.4. Credits
- •Bibliography
- •Appendix A. Contributed Scripts
- •Appendix C. Exit Codes With Special Meanings
- •Appendix D. A Detailed Introduction to I/O and I/O Redirection
- •Appendix E. Localization
- •Appendix F. History Commands
- •Appendix G. A Sample .bashrc File
- •Appendix H. Converting DOS Batch Files to Shell Scripts
- •Appendix I. Exercises
- •Appendix J. Copyright
Chapter 20. Subshells
Running a shell script launches another instance of the command processor. Just as your commands are interpreted at the command line prompt, similarly does a script batch process a list of commands in a file. Each shell script running is, in effect, a subprocess of the parent shell, the one that gives you the prompt at the console or in an xterm window.
A shell script can also launch subprocesses. These subshells let the script do parallel processing, in effect executing multiple subtasks simultaneously.
Command List in Parentheses
( command1; command2; command3; ... )
A command list embedded between parentheses runs as a subshell.
Variables in a subshell are not visible outside the block of code in the subshell. They are not accessible to the parent process, to the shell that launched the subshell. These are, in effect, local variables.
Example 20−1. Variable scope in a subshell
#!/bin/bash
# subshell.sh
echo
outer_variable=Outer
(
inner_variable=Inner
echo "From subshell, \"inner_variable\" = $inner_variable" echo "From subshell, \"outer\" = $outer_variable"
)
echo
if [ −z "$inner_variable" ] then
echo "inner_variable undefined in main body of shell" else
echo "inner_variable defined in main body of shell"
fi
echo "From main body of shell, \"inner_variable\" = $inner_variable"
#$inner_variable will show as uninitialized because
#variables defined in a subshell are "local variables".
echo
exit 0
Chapter 20. Subshells |
238 |
Advanced Bash−Scripting Guide
See also Example 32−1.
+
Directory changes made in a subshell do not carry over to the parent shell.
Example 20−2. List User Profiles
#!/bin/bash
#allprofs.sh: print all user profiles
#This script written by Heiner Steven, and modified by the document author.
FILE=.bashrc # |
File containing user profile, |
|||
|
#+ |
was ".profile" |
in original script. |
|
for |
home in `awk |
−F: '{print $6}' |
/etc/passwd` |
|
do |
|
|
|
|
[ |
−d "$home" ] |
|| continue |
# |
If no home directory, go to next. |
[ |
−r "$home" ] |
|| continue |
# |
If not readable, go to next. |
(cd $home; [ −e $FILE ] && less |
$FILE) |
|||
done |
|
|
|
|
# When script terminates, there is no need to 'cd' back to original directory, #+ because 'cd $home' takes place in a subshell.
exit 0
A subshell may be used to set up a "dedicated environment" for a command group.
COMMAND1
COMMAND2
COMMAND3
(
IFS=:
PATH=/bin unset TERMINFO set −C
shift 5 COMMAND4 COMMAND5
exit 3 # Only exits the subshell.
)
# The parent shell has not been affected, and the environment is preserved. COMMAND6
COMMAND7
One application of this is testing whether a variable is defined.
if (set −u; : $variable) 2> /dev/null then
echo "Variable is set."
fi
# Could also be written [[ |
${variable−x} != x || ${variable−y} != y ]] |
||
# |
or |
[[ |
${variable−x} != x$variable ]] |
# |
or |
[[ |
${variable+x} = x ]]) |
Another application is checking for a lock file: |
|||
if (set −C; : > lock_file) |
2> /dev/null |
||
|
|
|
|
Chapter 20. Subshells |
239 |
Advanced Bash−Scripting Guide
then
echo "Another user is already running that script." exit 65
fi
# Thanks, S.C.
Processes may execute in parallel within different subshells. This permits breaking a complex task into subcomponents processed concurrently.
Example 20−3. Running parallel processes in subshells
(cat list1 list2 list3 | sort | uniq > list123) & (cat list4 list5 list6 | sort | uniq > list456) &
#Merges and sorts both sets of lists simultaneously.
#Running in background ensures parallel execution.
#Same effect as
#cat list1 list2 list3 | sort | uniq > list123 &
#cat list4 list5 list6 | sort | uniq > list456 &
wait # Don't execute the next command until subshells finish.
diff list123 list456
Redirecting I/O to a subshell uses the "|" pipe operator, as in ls −al | (command).
A command block between curly braces does not launch a subshell.
{ command1; command2; command3; ... }
Chapter 20. Subshells |
240 |
Chapter 21. Restricted Shells
Disabled commands in restricted shells
Running a script or portion of a script in restricted mode disables certain commands that would otherwise be available. This is a security measure intended to limit the privileges of the script user and to minimize possible damage from running the script.
Using cd to change the working directory.
Changing the values of the $PATH, $SHELL, $BASH_ENV, or $ENV environmental variables.
Reading or changing the $SHELLOPTS, shell environmental options.
Output redirection.
Invoking commands containing one or more /'s.
Invoking exec to substitute a different process for the shell.
Various other commands that would enable monkeying with or attempting to subvert the script for an unintended purpose.
Getting out of restricted mode within the script.
Example 21−1. Running a script in restricted mode
#!/bin/bash
#Starting the script with "#!/bin/bash −r"
#runs entire script in restricted mode.
echo
echo "Changing directory." cd /usr/local
echo "Now in `pwd`"
echo "Coming back home." cd
echo "Now in `pwd`" echo
# Everything up to here in normal, unrestricted mode.
set −r |
|
# set −−restricted |
has same effect. |
echo "==> Now in restricted mode. <=="
echo echo
echo "Attempting directory change in restricted mode." cd ..
echo "Still in `pwd`"
Chapter 21. Restricted Shells |
241 |
Advanced Bash−Scripting Guide
echo echo
echo "\$SHELL = $SHELL"
echo "Attempting to change shell in restricted mode." SHELL="/bin/ash"
echo
echo "\$SHELL= $SHELL"
echo echo
echo "Attempting to redirect output in restricted mode." ls −l /usr/bin > bin.files
ls −l bin.files |
# Try to list attempted file creation effort. |
|
echo |
|
|
exit |
0 |
|
|
|
|
Chapter 21. Restricted Shells |
242 |