📄 subshells.html
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><HTML><HEAD><TITLE>Subshells</TITLE><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+"><LINKREL="HOME"TITLE="Advanced Bash-Scripting Guide"HREF="index.html"><LINKREL="UP"TITLE="Advanced Topics"HREF="part5.html"><LINKREL="PREVIOUS"TITLE="Applications"HREF="redirapps.html"><LINKREL="NEXT"TITLE="Restricted Shells"HREF="restricted-sh.html"><METAHTTP-EQUIV="Content-Style-Type"CONTENT="text/css"><LINKREL="stylesheet"HREF="common/kde-common.css"TYPE="text/css"><METAHTTP-EQUIV="Content-Type"CONTENT="text/html; charset=iso-8859-1"><METAHTTP-EQUIV="Content-Language"CONTENT="en"><LINKREL="stylesheet"HREF="common/kde-localised.css"TYPE="text/css"TITLE="KDE-English"><LINKREL="stylesheet"HREF="common/kde-default.css"TYPE="text/css"TITLE="KDE-Default"></HEAD><BODYCLASS="CHAPTER"BGCOLOR="#FFFFFF"TEXT="#000000"LINK="#AA0000"VLINK="#AA0055"ALINK="#AA0000"STYLE="font-family: sans-serif;"><DIVCLASS="NAVHEADER"><TABLESUMMARY="Header navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">Advanced Bash-Scripting Guide: An in-depth exploration of the art of shell scripting</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><AHREF="redirapps.html"ACCESSKEY="P">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom"></TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="restricted-sh.html"ACCESSKEY="N">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="CHAPTER"><H1><ANAME="SUBSHELLS"></A>Chapter 20. Subshells</H1><P><ANAME="SUBSHELLSREF"></A></P><P>Running a shell script launches a new process, a <ICLASS="FIRSTTERM">subshell</I>.</P><TABLECLASS="SIDEBAR"BORDER="1"CELLPADDING="5"><TR><TD><DIVCLASS="SIDEBAR"><ANAME="AEN16669"></A><P>Definition: A <ICLASS="FIRSTTERM">subshell</I> is a process launched by a shell (or <ICLASS="FIRSTTERM">shell script</I>).</P></DIV></TD></TR></TABLE><P>A subshell is a separate instance of the command processor -- the <ICLASS="FIRSTTERM">shell</I> that gives you the prompt at the console or in an <ICLASS="FIRSTTERM">xterm</I> window. Just as your commands are interpreted at the command line prompt, similarly does a script <AHREF="timedate.html#BATCHPROCREF">batch-process</A> a list of commands. Each shell script running is, in effect, a subprocess (<AHREF="othertypesv.html#CHILDREF">child process</A>) of the <AHREF="internal.html#FORKREF">parent</A> shell.</P><P>A shell script can itself launch subprocesses. These <ICLASS="FIRSTTERM">subshells</I> let the script do parallel processing, in effect executing multiple subtasks simultaneously.</P><P> <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # subshell-test.sh 3 4 ( 5 # Inside parentheses, and therefore a subshell . . . 6 while [ 1 ] # Endless loop. 7 do 8 echo "Subshell running . . ." 9 done 10 ) 11 12 # Script will run forever, 13 #+ or at least until terminated by a Ctl-C. 14 15 exit $? # End of script (but will never get here). 16 17 18 19 Now, run the script: 20 sh subshell-test.sh 21 22 And, while the script is running, from a different xterm: 23 ps -ef | grep subshell-test.sh 24 25 UID PID PPID C STIME TTY TIME CMD 26 500 2698 2502 0 14:26 pts/4 00:00:00 sh subshell-test.sh 27 500 2699 2698 21 14:26 pts/4 00:00:24 sh subshell-test.sh 28 29 ^^^^ 30 31 Analysis: 32 PID 2698, the script, launched PID 2699, the subshell. 33 34 Note: The "UID ..." line would be filtered out by the "grep" command, 35 but is shown here for illustrative purposes.</PRE></TD></TR></TABLE> </P><P>In general, an <AHREF="external.html#EXTERNALREF">external command</A> in a script <AHREF="internal.html#FORKREF">forks off</A> a subprocess, <ANAME="AEN16686"HREF="#FTN.AEN16686">[1]</A> whereas a Bash <AHREF="internal.html#BUILTINREF">builtin</A> does not. For this reason, builtins execute more quickly than their external command equivalents.</P><DIVCLASS="VARIABLELIST"><P><B><ANAME="SUBSHELLPARENS1"></A>Command List within Parentheses</B></P><DL><DT>( command1; command2; command3; ... )</DT><DD><P>A command list embedded between <TTCLASS="REPLACEABLE"><I>parentheses</I></TT> runs as a subshell.</P></DD></DL></DIV><P><ANAME="PARVIS"></A>Variables in a subshell are <SPANCLASS="emphasis"><ICLASS="EMPHASIS">not</I></SPAN> visible outside the block of code in the subshell. They are not accessible to the <AHREF="internal.html#FORKREF">parent process</A>, to the shell that launched the subshell. These are, in effect, <AHREF="localvar.html#LOCALREF">local variables</A>.</P><DIVCLASS="EXAMPLE"><HR><ANAME="SUBSHELL"></A><P><B>Example 20-1. Variable scope in a subshell</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # subshell.sh 3 4 echo 5 6 echo "We are outside the subshell." 7 echo "Subshell level OUTSIDE subshell = $BASH_SUBSHELL" 8 # Bash, version 3, adds the new $BASH_SUBSHELL variable. 9 echo; echo 10 11 outer_variable=Outer 12 global_variable= 13 # Define global variable for "storage" of 14 #+ value of subshell variable. 15 16 ( 17 echo "We are inside the subshell." 18 echo "Subshell level INSIDE subshell = $BASH_SUBSHELL" 19 inner_variable=Inner 20 21 echo "From inside subshell, \"inner_variable\" = $inner_variable" 22 echo "From inside subshell, \"outer\" = $outer_variable" 23 24 global_variable="$inner_variable" # Will this allow "exporting" 25 #+ a subshell variable? 26 ) 27 28 echo; echo 29 echo "We are outside the subshell." 30 echo "Subshell level OUTSIDE subshell = $BASH_SUBSHELL" 31 echo 32 33 if [ -z "$inner_variable" ] 34 then 35 echo "inner_variable undefined in main body of shell" 36 else 37 echo "inner_variable defined in main body of shell" 38 fi 39 40 echo "From main body of shell, \"inner_variable\" = $inner_variable" 41 # $inner_variable will show as blank (uninitialized) 42 #+ because variables defined in a subshell are "local variables". 43 # Is there a remedy for this? 44 echo "global_variable = "$global_variable"" # Why doesn't this work? 45 46 echo 47 48 # ======================================================================= 49 50 # Additionally ... 51 52 echo "-----------------"; echo 53 54 var=41 # Global variable. 55 56 ( let "var+=1"; echo "\$var INSIDE subshell = $var" ) # 42 57 58 echo "\$var OUTSIDE subshell = $var" # 41 59 # Variable operations inside a subshell, even to a GLOBAL variable 60 #+ do not affect the value of the variable outside the subshell! 61 62 63 exit 0 64 65 # Question: 66 # -------- 67 # Once having exited a subshell, 68 #+ is there any way to reenter that very same subshell 69 #+ to modify or access the subshell variables?</PRE></TD></TR></TABLE><HR></DIV><P>See also <AHREF="gotchas.html#SUBPIT">Example 31-2</A>.</P><TABLECLASS="SIDEBAR"BORDER="1"CELLPADDING="5"><TR><TD><DIVCLASS="SIDEBAR"><ANAME="AEN16709"></A><P><ANAME="SCOPEREF"></A></P><P><SPANCLASS="emphasis"><ICLASS="EMPHASIS">Definition:</I></SPAN> The <ICLASS="FIRSTTERM">scope</I> of a variable is the context in which it has meaning, in which it has a <ICLASS="FIRSTTERM">value</I> that can be referenced. For example, the scope of a <AHREF="localvar.html#LOCALREF1">local
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -