Reworded some existing text. Added text to the "I/O Redirection" section.

Still not ready to be published.
This commit is contained in:
franl 2002-10-24 11:25:37 +00:00
parent c7db353e2f
commit c23c6e9353
1 changed files with 128 additions and 77 deletions

View File

@ -90,7 +90,7 @@
<title>Overview</title>
<para>
The Bourne Again Shell (Bash) is the primary shell of GNU system. It is
The Bourne Again Shell (Bash) is the primary shell of the GNU system. It is
compatible with the Bourne shell, which is one of the oldest UNIX shells,
but it has many enhancements that make it superior to the Bourne shell for
programming. A Bash program (or, more commonly, a "Bash
@ -147,8 +147,7 @@
<title>Feedback</title>
<para>
Feedback is most certainly welcome for this document. Send your additions,
comments and criticisms to the author.
Feedback is welcome. Send your comments and/or criticisms to the author.
</para>
</sect2>
@ -193,7 +192,7 @@
that Bash is an <emphasis>interactive</emphasis> shell. If you've ever
logged into a UNIX system, then you've probably used an interactive shell.
Bash is the default interactive shell of the GNU/Linux system (and you
might find it installed on commercial UNIX systems). Sometimes, the
might also find it installed on commercial UNIX systems). Sometimes, the
commands that Bash reads come from a file called a <emphasis>shell
script</emphasis>. When this happens, we say that Bash is a
<emphasis>non-interactive</emphasis> shell. In this case, Bash reads each
@ -231,8 +230,7 @@
help. It's possible that you do not have Bash installed on your system.
If this is the case, you'll have to download the source code for Bash,
build it, and install it. If you've never done those things, ask your
system administrator or local guru for help. It's not hard to download,
build, and install Bash.
system administrator or local guru for help. It's not hard to do.
</para>
</sect2>
@ -242,10 +240,9 @@
<para>
Let's start with a simple Bash script and work up to more complex ones
later. Just about the simplest program you can write in any programming
language is what's called a <emphasis>Hello world</emphasis> program,
which is a program that simply outputs the text "Hello
world". <xref linkend="ex-hello-script"/> shows a Bash script to
do that.
language is a <emphasis>Hello world</emphasis> program, which is a program
that simply outputs the text "Hello world". <xref
linkend="ex-hello-script"/> shows a Bash script to do that.
</para>
<blockquote>
@ -266,7 +263,8 @@ echo Hello world</programlisting>
<computeroutput><command>test</command></computeroutput> command in almost
every shell, and it's too easy to accidentally run the built-in
<computeroutput><command>test</command></computeroutput> command instead
of your own script.
of your own script. I suggest that you name this script
"<filename>hello</filename>".
</para>
<para>
@ -287,12 +285,12 @@ echo Hello world</programlisting>
<para>
Once you've created your <emphasis>Hello world</emphasis> script, you can
execute it in a variety of ways. Let's assume that you named the script
<filename>hello</filename> and that it exists in your current working
<filename>hello</filename> and it exists in your current working
directory. <xref linkend="ex-running-hello"/> shows how to execute the
script. In this example, the shell's prompt is shown as
"<computeroutput>bash$</computeroutput>" to emphasize which
shell is displaying the prompt. Your shell's prompt might look different,
but that's OK.
"<computeroutput>bash$</computeroutput>" to emphasize which shell is
displaying the prompt. Your shell's prompt might look different, but
that's OK.
</para>
<para>
@ -333,11 +331,12 @@ Hello world</programlisting>
<listitem>
<para>
Change the permissions on the script to allow you to execute it. This
can be done with a command like this: <computeroutput><command>chmod
u+x hello</command></computeroutput>. You don't have to grant execute
permission just to yourself. This command allows everyone to execute
your script: <computeroutput><command>chmod ugo+x
hello</command></computeroutput>.
can be done with the command "<computeroutput><command>chmod u+x
hello</command></computeroutput>". You don't have to grant execute
permission just to yourself. The command
"<computeroutput><command>chmod ugo+x
hello</command></computeroutput>" allows everyone to execute your
script.
</para>
</listitem>
@ -353,10 +352,10 @@ Hello world</programlisting>
<para>
Some people satisfy the requirement in item #<xref
linkend="item-dir-path"/> by listing the directory
"<filename>.</filename>" into the value of their
<envar>PATH</envar> environment variable, but doing that creates a subtle
security problem (that is beyond the scope of this document to describe).
A better way to satisfy this requirement is to do this:
"<filename>.</filename>" in the value of their <envar>PATH</envar>
environment variable, but doing that creates a subtle security problem
(that is beyond the scope of this document to describe). A better way to
satisfy this requirement is to do this:
</para>
<orderedlist>
@ -382,7 +381,7 @@ Hello world</programlisting>
(which is the file <filename>.bashrc</filename> in your home directory):
<blockquote>
<computeroutput>PATH="/path/to/your/home/dir/bin:$PATH"</computeroutput>
<computeroutput>PATH="/home/your_home_dir/bin:$PATH"</computeroutput>
</blockquote>
</para>
</listitem>
@ -407,23 +406,24 @@ Hello world</programlisting>
Let's understand how the script shown in <xref linkend="ex-hello-script"/>
works. It's just two lines long, but both lines are significant. Neither
line can be left out. The first line
("<computeroutput>#!/bin/bash</computeroutput>") tells the
operating system which shell to spawn to execute this script. Unlike
programs written in compiled languages, such as C, Pascal, or C++, a Bash
script is <emphasis>interpreted</emphasis>, which means that some other
program (the <emphasis>interpreter</emphasis>) must read the script and
perform the commands found in the script. Bash is the interpreter for a
Bash script. A good analogy is to think of a chef cooking a meal by
reading a recipe. In this case, your script is the recipe, and Bash is
the chef.
("<computeroutput>#!/bin/bash</computeroutput>") tells the operating
system which shell to spawn to execute this script. Unlike programs
written in compiled languages, such as C, Pascal, or C++, a Bash script is
<emphasis>interpreted</emphasis>, which means that some other program (the
<emphasis>interpreter</emphasis>) must read the script and execute the
commands in the script. Bash is the interpreter for a Bash script. A
good analogy is to think of a chef cooking a meal by reading a recipe. In
this case, your script is the recipe, and Bash is the chef.
</para>
<para>
Your script's first line must specify the full pathname of the Bash shell
on your system. If your Bash shell is installed somewhere other than
<filename>/bin/bash</filename>, then you must know where it is installed
and write your script accordingly. If you are using Linux, then Bash is
always installed in <filename>/bin/bash</filename>.
on immediately after the characters
"<computeroutput>#!</computeroutput>". If your Bash shell is installed
somewhere other than <filename>/bin/bash</filename>, then you must know
where it is installed and write the first line of your script accordingly.
If you are using Linux, then Bash is always installed in
<filename>/bin/bash</filename>.
</para>
<para>
@ -441,42 +441,39 @@ Hello world</programlisting>
perfectly OK to do so. In a Bash script, the
<computeroutput><command>echo</command></computeroutput> command is used
to produce output. It simply outputs it's arguments with a single space
between each one.
between each one to the terminal on which the script is running.
</para>
<para>
In general, Bash executes a script by reading each line of the script from
top to bottom, validating that each line is syntactically correct, and, if
there is no syntax error, executing the command on each line as if it had
been typed into an interactive shell. So you can put any command in a
Bash script that you would normally type to an interactive shell, and it
will work the same way (see <xref
In general, Bash executes the commands in a script from top to bottom,
executing each command as if it had been typed into an interactive shell.
So you can put any command in a Bash script that you would normally type
to an interactive shell, and it will work the same way (see <xref
linkend="sect-interactive-vs-noninteractive"/> for a very short list of
exceptions to this rule). But what about that
<emphasis>shebang</emphasis> line
("<computeroutput>#!/bin/bash</computeroutput>")? What
happens when Bash reads and executes that line?
("<computeroutput>#!/bin/bash</computeroutput>")? What happens when Bash
reads and executes that line?
</para>
<para>
The answer is: nothing. The text between a
"<computeroutput>#</computeroutput>" character and the end of
the same line is a <emphasis>comment</emphasis>. A comment is completely
ignored by Bash. You should use comments to make your script readable by
others by including information that helps the reader understand your
script. If the
"<computeroutput>#!/bin/bash</computeroutput>" line is a
comment that is igored by Bash, then why can't you leave it out? Because
although it is ignored by Bash, it is not ignored by the operating system,
which uses the first line of the script to determine which shell to spawn
to interpret the script. Thus, the first line of a Bash script cannot be
omitted, even though it is ignored by Bash.
"<computeroutput>#</computeroutput>" character and the end of the same
line is a <emphasis>comment</emphasis>. A comment is completely ignored
by Bash. You should use comments to make your script readable by others
by including information that helps the reader understand your script. If
the "<computeroutput>#!/bin/bash</computeroutput>" line is a comment that
is ignored by Bash, why can't you leave it out? Although it is ignored by
Bash, it is not ignored by the operating system, which uses the first line
of the script to determine which shell to spawn to interpret the script.
Thus, the first line of a Bash script cannot be omitted, even though it is
ignored by Bash.
</para>
<para>
After Bash has read the last line of the script, Bash terminates, thus
terminating your script. Later, we'll see how you can control just when
and how your script terminates.
After Bash has executed the command on the last line of the script, Bash
terminates, thus terminating your script. Later, we'll see how you can
control just when and how your script terminates.
</para>
</sect2>
@ -502,12 +499,16 @@ Hello world</programlisting>
user doesn't necessarilly have the same aliases defined as you. And
if someone else wrote a script that you were using, then any aliases
they use in the script might mean something completely different when
you run the script. That is why Bash never expands aliases within a
you run the script. That is why aliases never work within a Bash
script. Aliases only work in interactive shells.
</para>
</listitem>
<listitem>
<para>
<emphasis>What else?</emphasis>
</para>
<para>*** UNDER CONSTRUCTION ***</para>
<!--
*************************************************************
@ -532,28 +533,29 @@ Hello world</programlisting>
<para>
A running program is called a <emphasis>process</emphasis>. When you type a
command, such as "<computeroutput><command>ls</command></computeroutput>",
that invokes a program, Bash spawns a new process to execute that program.
The process executing the command exists only for the time it takes the
command to execute, and then the process terminates. When Bash starts a
process for a command typed to an interactive shell, the process is
connected to several <emphasis>I/O streams</emphasis>. Think of an I/O
stream as a hose that has one end connected to the process and the other end
connected to a terminal. Data flows through an I/O stream either from the
process to the terminal (this is how the process produces output that is
displayed to the user) or from the terminal to the process (this is how the
process reads what the user types).
Bash spawns a new process to execute the
<computeroutput><command>ls</command></computeroutput> program. The process
exists only for the time it takes the command to execute, and then the
process terminates. When Bash starts a process for a command typed to an
interactive shell, the process is connected to several <emphasis>I/O
streams</emphasis>. Think of an I/O stream as a hose that has one end
connected to the process and the other end connected to a terminal. Data
flows through an I/O stream like water flows through a hose. The data flows
either from the process to the terminal (this is how the process produces
output) or from the terminal to the process (this is how the process reads
input from the keyboard).
</para>
<para>
A process can create and destroy I/O streams as it pleases, but when it
first starts, there are always three <emphasis>standard I/O
streams</emphasis> connected to the process my the operating system:
streams</emphasis> connected to the process:
</para>
<itemizedlist>
<listitem>Standard input</listitem>
<listitem>Standard output</listitem>
<listitem>Standard error</listitem>
<listitem>Standard input (stdin)</listitem>
<listitem>Standard output (stdout)</listitem>
<listitem>Standard error (stderr)</listitem>
</itemizedlist>
<para>
@ -561,9 +563,58 @@ Hello world</programlisting>
a process reads input from its terminal. <emphasis>Standard
output</emphasis> is the name of the I/O stream over which a process writes
output to its terminal. <emphasis>Standard error</emphasis> is the name of
the I/O stream over which a process write error messages to its terminal.
the I/O stream over which a process write error messages to its terminal.
These standard I/O streams are sometimes referred to using their shorthand
names: stdin, stdout, and stderr.
</para>
<para>
When your Bash script is running, it is a process just like any other, so it
also has these three standard I/O streams. The
<computeroutput><command>echo</command></computeroutput> command writes its
output to standard output. Since standard output is connected by default to
the terminal on which the script is running, the output of the
<computeroutput><command>echo</command></computeroutput> typically appears
on that terminal. But it is possible to <emphasis>redirect</emphasis> an
I/O stream so that it is not connected to the terminal but to a file on
disk. <xref linkend="ex-redirect-stdout"/> shows how to write an
<computeroutput><command>echo</command></computeroutput> command that
redirects standard output to a file.
</para>
<para>
<blockquote>
<example id="ex-redirect-stdout">
<title>Redirecting Standard Output</title>
<programlisting>
#!/bin/bash
echo Hello world > xyz</programlisting>
</example>
</blockquote>
</para>
<para>
In this example, the "<computeroutput>> xyz</computeroutput>" at the end of
the "<computeroutput>echo Hello world</computeroutput>" command tells Bash
to temporarilly redirect the script's standard output stream from its
current destination (the terminal) to the file "<filename>xyz</filename>"
for the duration of the
<computeroutput><command>echo</command></computeroutput> command. You can
specify any relative or absolute pathname after the
"<computeroutput>&gt;</computeroutput>".
</para>
<warning>
<title>Warning!</title>
<para>
If the file specified in the output redirection already exists, it is
overwritten! Always be sure that you don't have any valuable data in the
file that is going to be overwritten by output redirection.
</para>
</warning>
<para>*** UNDER CONSTRUCTION ***</para>
<!--
*************************************************************