mirror of https://github.com/tLDP/LDP
Reworded some existing text. Added text to the "I/O Redirection" section.
Still not ready to be published.
This commit is contained in:
parent
c7db353e2f
commit
c23c6e9353
|
@ -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>></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>
|
||||
<!--
|
||||
*************************************************************
|
||||
|
|
Loading…
Reference in New Issue