⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 subshells.html

📁 一本完整的描述Unix Shell 编程的工具书的所有范例
💻 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.57"><LINKREL="HOME"TITLE="Advanced Bash-Scripting Guide"HREF="index.html"><LINKREL="UP"TITLE="Advanced Topics"HREF="part4.html"><LINKREL="PREVIOUS"TITLE="Globbing"HREF="globbingref.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"><TABLEWIDTH="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="globbingref.html">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom"></TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="restricted-sh.html">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="CHAPTER"><H1><ANAME="SUBSHELLS">Chapter 20. Subshells</A></H1><P><ANAME="SUBSHELLSREF"></A></P><P>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 <AHREF="internal.html#FORKREF">parent</A> shell,        the one that gives you the prompt at the console or in an        <ICLASS="FIRSTTERM">xterm</I> window.</P><P>A shell script can also launch subprocesses. These        <ICLASS="EMPHASIS">subshells</I> let the script do        parallel processing, in effect executing multiple subtasks        simultaneously.</P><TABLECLASS="SIDEBAR"BORDER="1"CELLPADDING="5"><TR><TD><DIVCLASS="SIDEBAR"><ANAME="AEN13908"></A><P>In general, an <AHREF="external.html#EXTERNALREF">external	command</A> in a script <AHREF="internal.html#FORKREF">forks	off</A> a subprocess, whereas a Bash <AHREF="internal.html#BUILTINREF">builtin</A> does not. For this reason,	builtins execute more quickly than their external command	equivalents.</P></DIV></TD></TR></TABLE><DIVCLASS="VARIABLELIST"><P><B><ANAME="SUBSHELLPARENS1"></A>Command List in	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><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><ANAME="PARVIS"></A>Variables in a subshell are          <ICLASS="EMPHASIS">not</I> 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></TD></TR></TABLE></DIV><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&nbsp;#!/bin/bash   2&nbsp;# subshell.sh   3&nbsp;   4&nbsp;echo   5&nbsp;   6&nbsp;echo "Subshell level OUTSIDE subshell = $BASH_SUBSHELL"   7&nbsp;# Bash, version 3, adds the new         $BASH_SUBSHELL variable.   8&nbsp;echo   9&nbsp;  10&nbsp;outer_variable=Outer  11&nbsp;  12&nbsp;(  13&nbsp;echo "Subshell level INSIDE subshell = $BASH_SUBSHELL"  14&nbsp;inner_variable=Inner  15&nbsp;  16&nbsp;echo "From subshell, \"inner_variable\" = $inner_variable"  17&nbsp;echo "From subshell, \"outer\" = $outer_variable"  18&nbsp;)  19&nbsp;  20&nbsp;echo  21&nbsp;echo "Subshell level OUTSIDE subshell = $BASH_SUBSHELL"  22&nbsp;echo  23&nbsp;  24&nbsp;if [ -z "$inner_variable" ]  25&nbsp;then  26&nbsp;  echo "inner_variable undefined in main body of shell"  27&nbsp;else  28&nbsp;  echo "inner_variable defined in main body of shell"  29&nbsp;fi  30&nbsp;  31&nbsp;echo "From main body of shell, \"inner_variable\" = $inner_variable"  32&nbsp;#  $inner_variable will show as uninitialized  33&nbsp;#+ because variables defined in a subshell are "local variables".  34&nbsp;#  Is there any remedy for this?  35&nbsp;  36&nbsp;echo  37&nbsp;  38&nbsp;exit 0</PRE></TD></TR></TABLE><HR></DIV><P>See also <AHREF="gotchas.html#SUBPIT">Example 31-2</A>.</P><P>+</P><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&nbsp;#!/bin/bash   2&nbsp;# allprofs.sh: print all user profiles   3&nbsp;   4&nbsp;# This script written by Heiner Steven, and modified by the document author.   5&nbsp;   6&nbsp;FILE=.bashrc  #  File containing user profile,   7&nbsp;              #+ was ".profile" in original script.   8&nbsp;   9&nbsp;for home in `awk -F: '{print $6}' /etc/passwd`  10&nbsp;do  11&nbsp;  [ -d "$home" ] || continue    # If no home directory, go to next.  12&nbsp;  [ -r "$home" ] || continue    # If not readable, go to next.  13&nbsp;  (cd $home; [ -e $FILE ] &#38;&#38; less $FILE)  14&nbsp;done  15&nbsp;  16&nbsp;#  When script terminates, there is no need to 'cd' back to original directory,  17&nbsp;#+ because 'cd $home' takes place in a subshell.  18&nbsp;  19&nbsp;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&nbsp;COMMAND1   2&nbsp;COMMAND2   3&nbsp;COMMAND3   4&nbsp;(   5&nbsp;  IFS=:   6&nbsp;  PATH=/bin   7&nbsp;  unset TERMINFO   8&nbsp;  set -C   9&nbsp;  shift 5  10&nbsp;  COMMAND4  11&nbsp;  COMMAND5  12&nbsp;  exit 3 # Only exits the subshell.  13&nbsp;)  14&nbsp;# The parent shell has not been affected, and the environment is preserved.  15&nbsp;COMMAND6  16&nbsp;COMMAND7</PRE></TD></TR></TABLE>            One application of this is testing whether a variable is defined.              <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;if (set -u; : $variable) 2&#62; /dev/null   2&nbsp;then   3&nbsp;  echo "Variable is set."   4&nbsp;fi     #  Variable has been set in current script,   5&nbsp;       #+ or is an an internal Bash variable,   6&nbsp;       #+ or is present in environment (has been exported).   7&nbsp;   8&nbsp;# Could also be written [[ ${variable-x} != x || ${variable-y} != y ]]   9&nbsp;# or                    [[ ${variable-x} != x$variable ]]  10&nbsp;# or                    [[ ${variable+x} = x ]]  11&nbsp;# or                    [[ ${variable-x} != x ]]</PRE></TD></TR></TABLE>            Another application is checking for a lock file:	      <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;if (set -C; : &#62; lock_file) 2&#62; /dev/null   2&nbsp;then   3&nbsp;  :   # lock_file didn't exist: no user running the script   4&nbsp;else   5&nbsp;  echo "Another user is already running that script."   6&nbsp;exit 65   7&nbsp;fi   8&nbsp;   9&nbsp;#  Code snippet by St閜hane Chazelas,  10&nbsp;#+ with modifications by Paulo Marcel Coelho Aragao.</PRE></TD></TR></TABLE>      </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&nbsp;	(cat list1 list2 list3 | sort | uniq &#62; list123) &#38;   2&nbsp;	(cat list4 list5 list6 | sort | uniq &#62; list456) &#38;   3&nbsp;	# Merges and sorts both sets of lists simultaneously.   4&nbsp;	# Running in background ensures parallel execution.   5&nbsp;	#   6&nbsp;	# Same effect as   7&nbsp;	#   cat list1 list2 list3 | sort | uniq &#62; list123 &#38;   8&nbsp;	#   cat list4 list5 list6 | sort | uniq &#62; list456 &#38;   9&nbsp;	  10&nbsp;	wait   # Don't execute the next command until subshells finish.  11&nbsp;	  12&nbsp;	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 <ICLASS="EMPHASIS">not</I> launch	  a subshell.</P><P>{ command1; command2; command3; ... }</P></TD></TR></TABLE></DIV></DIV><DIVCLASS="NAVFOOTER"><HRALIGN="LEFT"WIDTH="100%"><TABLEWIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top"><AHREF="globbingref.html">Prev</A></TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="index.html">Home</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top"><AHREF="restricted-sh.html">Next</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">Globbing</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="part4.html">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 + -