866 lines
14 KiB
HTML
866 lines
14 KiB
HTML
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
|||
|
<HTML
|
|||
|
><HEAD
|
|||
|
><TITLE
|
|||
|
>Subshells</TITLE
|
|||
|
><META
|
|||
|
NAME="GENERATOR"
|
|||
|
CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK
|
|||
|
REL="HOME"
|
|||
|
TITLE="Advanced Bash-Scripting Guide"
|
|||
|
HREF="index.html"><LINK
|
|||
|
REL="UP"
|
|||
|
TITLE="Advanced Topics"
|
|||
|
HREF="part5.html"><LINK
|
|||
|
REL="PREVIOUS"
|
|||
|
TITLE="Applications"
|
|||
|
HREF="redirapps.html"><LINK
|
|||
|
REL="NEXT"
|
|||
|
TITLE="Restricted Shells"
|
|||
|
HREF="restricted-sh.html"></HEAD
|
|||
|
><BODY
|
|||
|
CLASS="CHAPTER"
|
|||
|
BGCOLOR="#FFFFFF"
|
|||
|
TEXT="#000000"
|
|||
|
LINK="#0000FF"
|
|||
|
VLINK="#840084"
|
|||
|
ALINK="#0000FF"
|
|||
|
><DIV
|
|||
|
CLASS="NAVHEADER"
|
|||
|
><TABLE
|
|||
|
SUMMARY="Header navigation table"
|
|||
|
WIDTH="100%"
|
|||
|
BORDER="0"
|
|||
|
CELLPADDING="0"
|
|||
|
CELLSPACING="0"
|
|||
|
><TR
|
|||
|
><TH
|
|||
|
COLSPAN="3"
|
|||
|
ALIGN="center"
|
|||
|
>Advanced Bash-Scripting Guide: </TH
|
|||
|
></TR
|
|||
|
><TR
|
|||
|
><TD
|
|||
|
WIDTH="10%"
|
|||
|
ALIGN="left"
|
|||
|
VALIGN="bottom"
|
|||
|
><A
|
|||
|
HREF="redirapps.html"
|
|||
|
ACCESSKEY="P"
|
|||
|
>Prev</A
|
|||
|
></TD
|
|||
|
><TD
|
|||
|
WIDTH="80%"
|
|||
|
ALIGN="center"
|
|||
|
VALIGN="bottom"
|
|||
|
></TD
|
|||
|
><TD
|
|||
|
WIDTH="10%"
|
|||
|
ALIGN="right"
|
|||
|
VALIGN="bottom"
|
|||
|
><A
|
|||
|
HREF="restricted-sh.html"
|
|||
|
ACCESSKEY="N"
|
|||
|
>Next</A
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
><HR
|
|||
|
ALIGN="LEFT"
|
|||
|
WIDTH="100%"></DIV
|
|||
|
><DIV
|
|||
|
CLASS="CHAPTER"
|
|||
|
><H1
|
|||
|
><A
|
|||
|
NAME="SUBSHELLS"
|
|||
|
></A
|
|||
|
>Chapter 21. Subshells</H1
|
|||
|
><P
|
|||
|
><A
|
|||
|
NAME="SUBSHELLSREF"
|
|||
|
></A
|
|||
|
></P
|
|||
|
><P
|
|||
|
>Running a shell script launches a new process, a
|
|||
|
<I
|
|||
|
CLASS="FIRSTTERM"
|
|||
|
>subshell</I
|
|||
|
>.</P
|
|||
|
><TABLE
|
|||
|
CLASS="SIDEBAR"
|
|||
|
BORDER="1"
|
|||
|
CELLPADDING="5"
|
|||
|
><TR
|
|||
|
><TD
|
|||
|
><DIV
|
|||
|
CLASS="SIDEBAR"
|
|||
|
><A
|
|||
|
NAME="AEN18083"
|
|||
|
></A
|
|||
|
><P
|
|||
|
></P
|
|||
|
><P
|
|||
|
><TT
|
|||
|
CLASS="USERINPUT"
|
|||
|
><B
|
|||
|
>Definition:</B
|
|||
|
></TT
|
|||
|
>
|
|||
|
A <I
|
|||
|
CLASS="FIRSTTERM"
|
|||
|
>subshell</I
|
|||
|
> is a
|
|||
|
<A
|
|||
|
HREF="othertypesv.html#CHILDREF2"
|
|||
|
>child process</A
|
|||
|
> launched by a
|
|||
|
shell (or <I
|
|||
|
CLASS="FIRSTTERM"
|
|||
|
>shell script</I
|
|||
|
>).</P
|
|||
|
><P
|
|||
|
></P
|
|||
|
></DIV
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
><P
|
|||
|
>A subshell is a separate instance of the command processor
|
|||
|
-- the <I
|
|||
|
CLASS="FIRSTTERM"
|
|||
|
>shell</I
|
|||
|
> that gives you the prompt at
|
|||
|
the console or in an <I
|
|||
|
CLASS="FIRSTTERM"
|
|||
|
>xterm</I
|
|||
|
> window. Just
|
|||
|
as your commands are interpreted at the command-line prompt,
|
|||
|
similarly does a script <A
|
|||
|
HREF="timedate.html#BATCHPROCREF"
|
|||
|
>batch-process</A
|
|||
|
> a list of
|
|||
|
commands. Each shell script running is, in effect, a subprocess
|
|||
|
(<I
|
|||
|
CLASS="FIRSTTERM"
|
|||
|
>child process</I
|
|||
|
>) of the <A
|
|||
|
HREF="internal.html#FORKREF"
|
|||
|
>parent</A
|
|||
|
> shell.</P
|
|||
|
><P
|
|||
|
>A shell script can itself launch subprocesses. These
|
|||
|
<I
|
|||
|
CLASS="FIRSTTERM"
|
|||
|
>subshells</I
|
|||
|
> let the script do
|
|||
|
parallel processing, in effect executing multiple subtasks
|
|||
|
simultaneously.</P
|
|||
|
><P
|
|||
|
> <TABLE
|
|||
|
BORDER="0"
|
|||
|
BGCOLOR="#E0E0E0"
|
|||
|
WIDTH="100%"
|
|||
|
><TR
|
|||
|
><TD
|
|||
|
><FONT
|
|||
|
COLOR="#000000"
|
|||
|
><PRE
|
|||
|
CLASS="PROGRAMLISTING"
|
|||
|
>#!/bin/bash
|
|||
|
# subshell-test.sh
|
|||
|
|
|||
|
(
|
|||
|
# Inside parentheses, and therefore a subshell . . .
|
|||
|
while [ 1 ] # Endless loop.
|
|||
|
do
|
|||
|
echo "Subshell running . . ."
|
|||
|
done
|
|||
|
)
|
|||
|
|
|||
|
# Script will run forever,
|
|||
|
#+ or at least until terminated by a Ctl-C.
|
|||
|
|
|||
|
exit $? # End of script (but will never get here).
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Now, run the script:
|
|||
|
sh subshell-test.sh
|
|||
|
|
|||
|
And, while the script is running, from a different xterm:
|
|||
|
ps -ef | grep subshell-test.sh
|
|||
|
|
|||
|
UID PID PPID C STIME TTY TIME CMD
|
|||
|
500 2698 2502 0 14:26 pts/4 00:00:00 sh subshell-test.sh
|
|||
|
500 2699 2698 21 14:26 pts/4 00:00:24 sh subshell-test.sh
|
|||
|
|
|||
|
^^^^
|
|||
|
|
|||
|
Analysis:
|
|||
|
PID 2698, the script, launched PID 2699, the subshell.
|
|||
|
|
|||
|
Note: The "UID ..." line would be filtered out by the "grep" command,
|
|||
|
but is shown here for illustrative purposes.</PRE
|
|||
|
></FONT
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
>
|
|||
|
</P
|
|||
|
><P
|
|||
|
>In general, an <A
|
|||
|
HREF="external.html#EXTERNALREF"
|
|||
|
>external
|
|||
|
command</A
|
|||
|
> in a script <A
|
|||
|
HREF="internal.html#FORKREF"
|
|||
|
>forks
|
|||
|
off</A
|
|||
|
> a subprocess,
|
|||
|
<A
|
|||
|
NAME="AEN18102"
|
|||
|
HREF="#FTN.AEN18102"
|
|||
|
><SPAN
|
|||
|
CLASS="footnote"
|
|||
|
>[1]</SPAN
|
|||
|
></A
|
|||
|
>
|
|||
|
whereas a Bash <A
|
|||
|
HREF="internal.html#BUILTINREF"
|
|||
|
>builtin</A
|
|||
|
>
|
|||
|
does not. For this reason, builtins execute more quickly
|
|||
|
and use fewer system resources than their external command
|
|||
|
equivalents.</P
|
|||
|
><P
|
|||
|
></P
|
|||
|
><DIV
|
|||
|
CLASS="VARIABLELIST"
|
|||
|
><P
|
|||
|
><B
|
|||
|
><A
|
|||
|
NAME="SUBSHELLPARENS1"
|
|||
|
></A
|
|||
|
>Command List within
|
|||
|
Parentheses</B
|
|||
|
></P
|
|||
|
><DL
|
|||
|
><DT
|
|||
|
>( command1; command2; command3; ... )</DT
|
|||
|
><DD
|
|||
|
><P
|
|||
|
>A command list embedded between
|
|||
|
<TT
|
|||
|
CLASS="REPLACEABLE"
|
|||
|
><I
|
|||
|
>parentheses</I
|
|||
|
></TT
|
|||
|
> runs as a
|
|||
|
subshell.</P
|
|||
|
></DD
|
|||
|
></DL
|
|||
|
></DIV
|
|||
|
><P
|
|||
|
><A
|
|||
|
NAME="PARVIS"
|
|||
|
></A
|
|||
|
>Variables in a subshell are
|
|||
|
<EM
|
|||
|
>not</EM
|
|||
|
> visible outside the block of code
|
|||
|
in the subshell. They are not accessible to the <A
|
|||
|
HREF="internal.html#FORKREF"
|
|||
|
>parent process</A
|
|||
|
>, to the shell
|
|||
|
that launched the subshell. These are, in effect,
|
|||
|
variables <A
|
|||
|
HREF="localvar.html#LOCALREF"
|
|||
|
>local</A
|
|||
|
> to the
|
|||
|
<I
|
|||
|
CLASS="FIRSTTERM"
|
|||
|
>child process</I
|
|||
|
>.</P
|
|||
|
><DIV
|
|||
|
CLASS="EXAMPLE"
|
|||
|
><A
|
|||
|
NAME="SUBSHELL"
|
|||
|
></A
|
|||
|
><P
|
|||
|
><B
|
|||
|
>Example 21-1. Variable scope in a subshell</B
|
|||
|
></P
|
|||
|
><TABLE
|
|||
|
BORDER="0"
|
|||
|
BGCOLOR="#E0E0E0"
|
|||
|
WIDTH="100%"
|
|||
|
><TR
|
|||
|
><TD
|
|||
|
><FONT
|
|||
|
COLOR="#000000"
|
|||
|
><PRE
|
|||
|
CLASS="PROGRAMLISTING"
|
|||
|
>#!/bin/bash
|
|||
|
# subshell.sh
|
|||
|
|
|||
|
echo
|
|||
|
|
|||
|
echo "We are outside the subshell."
|
|||
|
echo "Subshell level OUTSIDE subshell = $BASH_SUBSHELL"
|
|||
|
# Bash, version 3, adds the new $BASH_SUBSHELL variable.
|
|||
|
echo; echo
|
|||
|
|
|||
|
outer_variable=Outer
|
|||
|
global_variable=
|
|||
|
# Define global variable for "storage" of
|
|||
|
#+ value of subshell variable.
|
|||
|
|
|||
|
(
|
|||
|
echo "We are inside the subshell."
|
|||
|
echo "Subshell level INSIDE subshell = $BASH_SUBSHELL"
|
|||
|
inner_variable=Inner
|
|||
|
|
|||
|
echo "From inside subshell, \"inner_variable\" = $inner_variable"
|
|||
|
echo "From inside subshell, \"outer\" = $outer_variable"
|
|||
|
|
|||
|
global_variable="$inner_variable" # Will this allow "exporting"
|
|||
|
#+ a subshell variable?
|
|||
|
)
|
|||
|
|
|||
|
echo; echo
|
|||
|
echo "We are outside the subshell."
|
|||
|
echo "Subshell level OUTSIDE subshell = $BASH_SUBSHELL"
|
|||
|
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 blank (uninitialized)
|
|||
|
#+ because variables defined in a subshell are "local variables".
|
|||
|
# Is there a remedy for this?
|
|||
|
echo "global_variable = "$global_variable"" # Why doesn't this work?
|
|||
|
|
|||
|
echo
|
|||
|
|
|||
|
# =======================================================================
|
|||
|
|
|||
|
# Additionally ...
|
|||
|
|
|||
|
echo "-----------------"; echo
|
|||
|
|
|||
|
var=41 # Global variable.
|
|||
|
|
|||
|
( let "var+=1"; echo "\$var INSIDE subshell = $var" ) # 42
|
|||
|
|
|||
|
echo "\$var OUTSIDE subshell = $var" # 41
|
|||
|
# Variable operations inside a subshell, even to a GLOBAL variable
|
|||
|
#+ do not affect the value of the variable outside the subshell!
|
|||
|
|
|||
|
|
|||
|
exit 0
|
|||
|
|
|||
|
# Question:
|
|||
|
# --------
|
|||
|
# Once having exited a subshell,
|
|||
|
#+ is there any way to reenter that very same subshell
|
|||
|
#+ to modify or access the subshell variables?</PRE
|
|||
|
></FONT
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
></DIV
|
|||
|
><P
|
|||
|
>See also <A
|
|||
|
HREF="internalvariables.html#BASHPIDREF"
|
|||
|
>$BASHPID</A
|
|||
|
> and
|
|||
|
<A
|
|||
|
HREF="gotchas.html#SUBPIT"
|
|||
|
>Example 34-2</A
|
|||
|
>.</P
|
|||
|
><TABLE
|
|||
|
CLASS="SIDEBAR"
|
|||
|
BORDER="1"
|
|||
|
CELLPADDING="5"
|
|||
|
><TR
|
|||
|
><TD
|
|||
|
><DIV
|
|||
|
CLASS="SIDEBAR"
|
|||
|
><A
|
|||
|
NAME="AEN18127"
|
|||
|
></A
|
|||
|
><P
|
|||
|
></P
|
|||
|
><P
|
|||
|
><A
|
|||
|
NAME="SCOPEREF"
|
|||
|
></A
|
|||
|
></P
|
|||
|
><P
|
|||
|
><TT
|
|||
|
CLASS="USERINPUT"
|
|||
|
><B
|
|||
|
>Definition:</B
|
|||
|
></TT
|
|||
|
> The
|
|||
|
<I
|
|||
|
CLASS="FIRSTTERM"
|
|||
|
>scope</I
|
|||
|
> of a variable is the
|
|||
|
context in which it has meaning, in which it has a
|
|||
|
<I
|
|||
|
CLASS="FIRSTTERM"
|
|||
|
>value</I
|
|||
|
> that can be referenced. For
|
|||
|
example, the scope of a <A
|
|||
|
HREF="localvar.html#LOCALREF1"
|
|||
|
>local
|
|||
|
variable</A
|
|||
|
> lies only within the function,
|
|||
|
block of code, or subshell within which it is defined,
|
|||
|
while the scope of a <I
|
|||
|
CLASS="FIRSTTERM"
|
|||
|
>global</I
|
|||
|
> variable
|
|||
|
is the entire script in which it appears.</P
|
|||
|
><P
|
|||
|
></P
|
|||
|
></DIV
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
><P
|
|||
|
><A
|
|||
|
NAME="SUBSHNLEVREF"
|
|||
|
></A
|
|||
|
></P
|
|||
|
><DIV
|
|||
|
CLASS="NOTE"
|
|||
|
><P
|
|||
|
></P
|
|||
|
><TABLE
|
|||
|
CLASS="NOTE"
|
|||
|
WIDTH="100%"
|
|||
|
BORDER="0"
|
|||
|
><TR
|
|||
|
><TD
|
|||
|
WIDTH="25"
|
|||
|
ALIGN="CENTER"
|
|||
|
VALIGN="TOP"
|
|||
|
><IMG
|
|||
|
SRC="../images/note.gif"
|
|||
|
HSPACE="5"
|
|||
|
ALT="Note"></TD
|
|||
|
><TD
|
|||
|
ALIGN="LEFT"
|
|||
|
VALIGN="TOP"
|
|||
|
><P
|
|||
|
>While the <A
|
|||
|
HREF="internalvariables.html#BASHSUBSHELLREF"
|
|||
|
>$BASH_SUBSHELL</A
|
|||
|
>
|
|||
|
internal variable indicates the nesting level of a
|
|||
|
subshell, the <A
|
|||
|
HREF="internalvariables.html#SHLVLREF"
|
|||
|
>$SHLVL</A
|
|||
|
>
|
|||
|
variable <EM
|
|||
|
>shows no change</EM
|
|||
|
> within
|
|||
|
a subshell.</P
|
|||
|
><P
|
|||
|
><TABLE
|
|||
|
BORDER="0"
|
|||
|
BGCOLOR="#E0E0E0"
|
|||
|
WIDTH="100%"
|
|||
|
><TR
|
|||
|
><TD
|
|||
|
><FONT
|
|||
|
COLOR="#000000"
|
|||
|
><PRE
|
|||
|
CLASS="PROGRAMLISTING"
|
|||
|
>echo " \$BASH_SUBSHELL outside subshell = $BASH_SUBSHELL" # 0
|
|||
|
( echo " \$BASH_SUBSHELL inside subshell = $BASH_SUBSHELL" ) # 1
|
|||
|
( ( echo " \$BASH_SUBSHELL inside nested subshell = $BASH_SUBSHELL" ) ) # 2
|
|||
|
# ^ ^ *** nested *** ^ ^
|
|||
|
|
|||
|
echo
|
|||
|
|
|||
|
echo " \$SHLVL outside subshell = $SHLVL" # 3
|
|||
|
( echo " \$SHLVL inside subshell = $SHLVL" ) # 3 (No change!)</PRE
|
|||
|
></FONT
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
>
|
|||
|
</P
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
></DIV
|
|||
|
><P
|
|||
|
>Directory changes made in a subshell do not carry over to the
|
|||
|
parent shell.</P
|
|||
|
><DIV
|
|||
|
CLASS="EXAMPLE"
|
|||
|
><A
|
|||
|
NAME="ALLPROFS"
|
|||
|
></A
|
|||
|
><P
|
|||
|
><B
|
|||
|
>Example 21-2. List User Profiles</B
|
|||
|
></P
|
|||
|
><TABLE
|
|||
|
BORDER="0"
|
|||
|
BGCOLOR="#E0E0E0"
|
|||
|
WIDTH="100%"
|
|||
|
><TR
|
|||
|
><TD
|
|||
|
><FONT
|
|||
|
COLOR="#000000"
|
|||
|
><PRE
|
|||
|
CLASS="PROGRAMLISTING"
|
|||
|
>#!/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</PRE
|
|||
|
></FONT
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
></DIV
|
|||
|
><P
|
|||
|
>A subshell may be used to set up a <SPAN
|
|||
|
CLASS="QUOTE"
|
|||
|
>"dedicated
|
|||
|
environment"</SPAN
|
|||
|
> for a command group.
|
|||
|
<TABLE
|
|||
|
BORDER="0"
|
|||
|
BGCOLOR="#E0E0E0"
|
|||
|
WIDTH="100%"
|
|||
|
><TR
|
|||
|
><TD
|
|||
|
><FONT
|
|||
|
COLOR="#000000"
|
|||
|
><PRE
|
|||
|
CLASS="PROGRAMLISTING"
|
|||
|
>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</PRE
|
|||
|
></FONT
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
>
|
|||
|
|
|||
|
As seen here, the <A
|
|||
|
HREF="internal.html#EXITREF"
|
|||
|
>exit</A
|
|||
|
>
|
|||
|
command only terminates the subshell in which it is running,
|
|||
|
<EM
|
|||
|
>not</EM
|
|||
|
> the parent shell or script.</P
|
|||
|
><P
|
|||
|
>One application of such a <SPAN
|
|||
|
CLASS="QUOTE"
|
|||
|
>"dedicated environment"</SPAN
|
|||
|
>
|
|||
|
is testing whether a variable is defined.
|
|||
|
<TABLE
|
|||
|
BORDER="0"
|
|||
|
BGCOLOR="#E0E0E0"
|
|||
|
WIDTH="100%"
|
|||
|
><TR
|
|||
|
><TD
|
|||
|
><FONT
|
|||
|
COLOR="#000000"
|
|||
|
><PRE
|
|||
|
CLASS="PROGRAMLISTING"
|
|||
|
>if (set -u; : $variable) 2> /dev/null
|
|||
|
then
|
|||
|
echo "Variable is set."
|
|||
|
fi # Variable has been set in current script,
|
|||
|
#+ or is an an internal Bash variable,
|
|||
|
#+ or is present in environment (has been exported).
|
|||
|
|
|||
|
# Could also be written [[ ${variable-x} != x || ${variable-y} != y ]]
|
|||
|
# or [[ ${variable-x} != x$variable ]]
|
|||
|
# or [[ ${variable+x} = x ]]
|
|||
|
# or [[ ${variable-x} != x ]]</PRE
|
|||
|
></FONT
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
></P
|
|||
|
><P
|
|||
|
>Another application is checking for a lock file:
|
|||
|
<TABLE
|
|||
|
BORDER="0"
|
|||
|
BGCOLOR="#E0E0E0"
|
|||
|
WIDTH="100%"
|
|||
|
><TR
|
|||
|
><TD
|
|||
|
><FONT
|
|||
|
COLOR="#000000"
|
|||
|
><PRE
|
|||
|
CLASS="PROGRAMLISTING"
|
|||
|
>if (set -C; : > lock_file) 2> /dev/null
|
|||
|
then
|
|||
|
: # lock_file didn't exist: no user running the script
|
|||
|
else
|
|||
|
echo "Another user is already running that script."
|
|||
|
exit 65
|
|||
|
fi
|
|||
|
|
|||
|
# Code snippet by St<53>phane Chazelas,
|
|||
|
#+ with modifications by Paulo Marcel Coelho Aragao.</PRE
|
|||
|
></FONT
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
>
|
|||
|
</P
|
|||
|
><P
|
|||
|
>+</P
|
|||
|
><P
|
|||
|
>Processes may execute in parallel within different
|
|||
|
subshells. This permits breaking a complex task into subcomponents
|
|||
|
processed concurrently.</P
|
|||
|
><DIV
|
|||
|
CLASS="EXAMPLE"
|
|||
|
><A
|
|||
|
NAME="PARALLEL-PROCESSES"
|
|||
|
></A
|
|||
|
><P
|
|||
|
><B
|
|||
|
>Example 21-3. Running parallel processes in subshells</B
|
|||
|
></P
|
|||
|
><TABLE
|
|||
|
BORDER="0"
|
|||
|
BGCOLOR="#E0E0E0"
|
|||
|
WIDTH="100%"
|
|||
|
><TR
|
|||
|
><TD
|
|||
|
><FONT
|
|||
|
COLOR="#000000"
|
|||
|
><PRE
|
|||
|
CLASS="PROGRAMLISTING"
|
|||
|
> (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</PRE
|
|||
|
></FONT
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
></DIV
|
|||
|
><P
|
|||
|
>Redirecting I/O to a subshell uses the <SPAN
|
|||
|
CLASS="QUOTE"
|
|||
|
>"|"</SPAN
|
|||
|
> pipe
|
|||
|
operator, as in <TT
|
|||
|
CLASS="USERINPUT"
|
|||
|
><B
|
|||
|
>ls -al | (command)</B
|
|||
|
></TT
|
|||
|
>.</P
|
|||
|
><DIV
|
|||
|
CLASS="NOTE"
|
|||
|
><P
|
|||
|
></P
|
|||
|
><TABLE
|
|||
|
CLASS="NOTE"
|
|||
|
WIDTH="100%"
|
|||
|
BORDER="0"
|
|||
|
><TR
|
|||
|
><TD
|
|||
|
WIDTH="25"
|
|||
|
ALIGN="CENTER"
|
|||
|
VALIGN="TOP"
|
|||
|
><IMG
|
|||
|
SRC="../images/note.gif"
|
|||
|
HSPACE="5"
|
|||
|
ALT="Note"></TD
|
|||
|
><TD
|
|||
|
ALIGN="LEFT"
|
|||
|
VALIGN="TOP"
|
|||
|
><P
|
|||
|
>A code block between <A
|
|||
|
HREF="special-chars.html#CODEBLOCKREF"
|
|||
|
>curly brackets</A
|
|||
|
> does
|
|||
|
<EM
|
|||
|
>not</EM
|
|||
|
> launch a subshell.</P
|
|||
|
><P
|
|||
|
>{ command1; command2; command3; . . . commandN; }</P
|
|||
|
><P
|
|||
|
><TABLE
|
|||
|
BORDER="0"
|
|||
|
BGCOLOR="#E0E0E0"
|
|||
|
WIDTH="100%"
|
|||
|
><TR
|
|||
|
><TD
|
|||
|
><FONT
|
|||
|
COLOR="#000000"
|
|||
|
><PRE
|
|||
|
CLASS="PROGRAMLISTING"
|
|||
|
>var1=23
|
|||
|
echo "$var1" # 23
|
|||
|
|
|||
|
{ var1=76; }
|
|||
|
echo "$var1" # 76</PRE
|
|||
|
></FONT
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
></P
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
></DIV
|
|||
|
></DIV
|
|||
|
><H3
|
|||
|
CLASS="FOOTNOTES"
|
|||
|
>Notes</H3
|
|||
|
><TABLE
|
|||
|
BORDER="0"
|
|||
|
CLASS="FOOTNOTES"
|
|||
|
WIDTH="100%"
|
|||
|
><TR
|
|||
|
><TD
|
|||
|
ALIGN="LEFT"
|
|||
|
VALIGN="TOP"
|
|||
|
WIDTH="5%"
|
|||
|
><A
|
|||
|
NAME="FTN.AEN18102"
|
|||
|
HREF="subshells.html#AEN18102"
|
|||
|
><SPAN
|
|||
|
CLASS="footnote"
|
|||
|
>[1]</SPAN
|
|||
|
></A
|
|||
|
></TD
|
|||
|
><TD
|
|||
|
ALIGN="LEFT"
|
|||
|
VALIGN="TOP"
|
|||
|
WIDTH="95%"
|
|||
|
><P
|
|||
|
>An external command invoked with an <A
|
|||
|
HREF="internal.html#EXECREF"
|
|||
|
>exec</A
|
|||
|
> does <EM
|
|||
|
>not</EM
|
|||
|
>
|
|||
|
(usually) fork off a subprocess / subshell.</P
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
><DIV
|
|||
|
CLASS="NAVFOOTER"
|
|||
|
><HR
|
|||
|
ALIGN="LEFT"
|
|||
|
WIDTH="100%"><TABLE
|
|||
|
SUMMARY="Footer navigation table"
|
|||
|
WIDTH="100%"
|
|||
|
BORDER="0"
|
|||
|
CELLPADDING="0"
|
|||
|
CELLSPACING="0"
|
|||
|
><TR
|
|||
|
><TD
|
|||
|
WIDTH="33%"
|
|||
|
ALIGN="left"
|
|||
|
VALIGN="top"
|
|||
|
><A
|
|||
|
HREF="redirapps.html"
|
|||
|
ACCESSKEY="P"
|
|||
|
>Prev</A
|
|||
|
></TD
|
|||
|
><TD
|
|||
|
WIDTH="34%"
|
|||
|
ALIGN="center"
|
|||
|
VALIGN="top"
|
|||
|
><A
|
|||
|
HREF="index.html"
|
|||
|
ACCESSKEY="H"
|
|||
|
>Home</A
|
|||
|
></TD
|
|||
|
><TD
|
|||
|
WIDTH="33%"
|
|||
|
ALIGN="right"
|
|||
|
VALIGN="top"
|
|||
|
><A
|
|||
|
HREF="restricted-sh.html"
|
|||
|
ACCESSKEY="N"
|
|||
|
>Next</A
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
><TR
|
|||
|
><TD
|
|||
|
WIDTH="33%"
|
|||
|
ALIGN="left"
|
|||
|
VALIGN="top"
|
|||
|
>Applications</TD
|
|||
|
><TD
|
|||
|
WIDTH="34%"
|
|||
|
ALIGN="center"
|
|||
|
VALIGN="top"
|
|||
|
><A
|
|||
|
HREF="part5.html"
|
|||
|
ACCESSKEY="U"
|
|||
|
>Up</A
|
|||
|
></TD
|
|||
|
><TD
|
|||
|
WIDTH="33%"
|
|||
|
ALIGN="right"
|
|||
|
VALIGN="top"
|
|||
|
>Restricted Shells</TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
></DIV
|
|||
|
></BODY
|
|||
|
></HTML
|
|||
|
>
|