Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Cooper M.Advanced bash-scripting guide.2002.pdf
Скачиваний:
13
Добавлен:
23.08.2013
Размер:
916.67 Кб
Скачать

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