📄 subshells.html
字号:
variable</A> lies only within the function, block of code, or subshell within which it is defined.</P></DIV></TD></TR></TABLE><P><ANAME="SUBSHNLEVREF"></A></P><DIVCLASS="NOTE"><TABLECLASS="NOTE"WIDTH="100%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="common/note.png"HSPACE="5"ALT="Note"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>While the <AHREF="variables2.html#BASHSUBSHELLREF">$BASH_SUBSHELL</A> internal variable indicates the nesting level of a subshell, the <AHREF="variables2.html#SHLVLREF">$SHLVL</A> variable <SPANCLASS="emphasis"><ICLASS="EMPHASIS">shows no change</I></SPAN> within a subshell.</P><P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 echo " \$BASH_SUBSHELL outside subshell = $BASH_SUBSHELL" # 0 2 ( echo " \$BASH_SUBSHELL inside subshell = $BASH_SUBSHELL" ) # 1 3 ( ( echo " \$BASH_SUBSHELL inside nested subshell = $BASH_SUBSHELL" ) ) # 2 4 # ^ ^ *** nested *** ^ ^ 5 6 echo 7 8 echo " \$SHLVL outside subshell = $SHLVL" # 3 9 ( echo " \$SHLVL inside subshell = $SHLVL" ) # 3 (No change!)</PRE></TD></TR></TABLE> </P></TD></TR></TABLE></DIV><P>Directory changes made in a subshell do not carry over to the parent shell.</P><DIVCLASS="EXAMPLE"><HR><ANAME="ALLPROFS"></A><P><B>Example 20-2. List User Profiles</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # allprofs.sh: print all user profiles 3 4 # This script written by Heiner Steven, and modified by the document author. 5 6 FILE=.bashrc # File containing user profile, 7 #+ was ".profile" in original script. 8 9 for home in `awk -F: '{print $6}' /etc/passwd` 10 do 11 [ -d "$home" ] || continue # If no home directory, go to next. 12 [ -r "$home" ] || continue # If not readable, go to next. 13 (cd $home; [ -e $FILE ] && less $FILE) 14 done 15 16 # When script terminates, there is no need to 'cd' back to original directory, 17 #+ because 'cd $home' takes place in a subshell. 18 19 exit 0</PRE></TD></TR></TABLE><HR></DIV><P>A subshell may be used to set up a <SPANCLASS="QUOTE">"dedicated environment"</SPAN> for a command group. <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 COMMAND1 2 COMMAND2 3 COMMAND3 4 ( 5 IFS=: 6 PATH=/bin 7 unset TERMINFO 8 set -C 9 shift 5 10 COMMAND4 11 COMMAND5 12 exit 3 # Only exits the subshell! 13 ) 14 # The parent shell has not been affected, and the environment is preserved. 15 COMMAND6 16 COMMAND7</PRE></TD></TR></TABLE> As seen here, the <AHREF="internal.html#EXITREF">exit</A> command only terminates the subshell in which it is running, <SPANCLASS="emphasis"><ICLASS="EMPHASIS">not</I></SPAN> the parent shell or script.</P><P>One application of such a <SPANCLASS="QUOTE">"dedicated environment"</SPAN> is testing whether a variable is defined. <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 if (set -u; : $variable) 2> /dev/null 2 then 3 echo "Variable is set." 4 fi # Variable has been set in current script, 5 #+ or is an an internal Bash variable, 6 #+ or is present in environment (has been exported). 7 8 # Could also be written [[ ${variable-x} != x || ${variable-y} != y ]] 9 # or [[ ${variable-x} != x$variable ]] 10 # or [[ ${variable+x} = x ]] 11 # or [[ ${variable-x} != x ]]</PRE></TD></TR></TABLE></P><P>Another application is checking for a lock file: <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 if (set -C; : > lock_file) 2> /dev/null 2 then 3 : # lock_file didn't exist: no user running the script 4 else 5 echo "Another user is already running that script." 6 exit 65 7 fi 8 9 # Code snippet by St閜hane Chazelas, 10 #+ with modifications by Paulo Marcel Coelho Aragao.</PRE></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><DIVCLASS="EXAMPLE"><HR><ANAME="PARALLEL-PROCESSES"></A><P><B>Example 20-3. Running parallel processes in subshells</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 (cat list1 list2 list3 | sort | uniq > list123) & 2 (cat list4 list5 list6 | sort | uniq > list456) & 3 # Merges and sorts both sets of lists simultaneously. 4 # Running in background ensures parallel execution. 5 # 6 # Same effect as 7 # cat list1 list2 list3 | sort | uniq > list123 & 8 # cat list4 list5 list6 | sort | uniq > list456 & 9 10 wait # Don't execute the next command until subshells finish. 11 12 diff list123 list456</PRE></TD></TR></TABLE><HR></DIV><P>Redirecting I/O to a subshell uses the <SPANCLASS="QUOTE">"|"</SPAN> pipe operator, as in <TTCLASS="USERINPUT"><B>ls -al | (command)</B></TT>.</P><DIVCLASS="NOTE"><TABLECLASS="NOTE"WIDTH="100%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="common/note.png"HSPACE="5"ALT="Note"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>A command block between <TTCLASS="REPLACEABLE"><I>curly braces</I></TT> does <SPANCLASS="emphasis"><ICLASS="EMPHASIS">not</I></SPAN> launch a subshell.</P><P>{ command1; command2; command3; . . . commandN; }</P></TD></TR></TABLE></DIV></DIV><H3CLASS="FOOTNOTES">Notes</H3><TABLEBORDER="0"CLASS="FOOTNOTES"WIDTH="100%"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="5%"><ANAME="FTN.AEN16686"HREF="subshells.html#AEN16686">[1]</A></TD><TDALIGN="LEFT"VALIGN="TOP"WIDTH="95%"><P>An external command invoked with an <AHREF="internal.html#EXECREF">exec</A> does <SPANCLASS="emphasis"><ICLASS="EMPHASIS">not</I></SPAN> (usually) fork off a subprocess / subshell.</P></TD></TR></TABLE><DIVCLASS="NAVFOOTER"><HRALIGN="LEFT"WIDTH="100%"><TABLESUMMARY="Footer navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top"><AHREF="redirapps.html"ACCESSKEY="P">Prev</A></TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="index.html"ACCESSKEY="H">Home</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top"><AHREF="restricted-sh.html"ACCESSKEY="N">Next</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">Applications</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="part5.html"ACCESSKEY="U">Up</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">Restricted Shells</TD></TR></TABLE></DIV></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -