|
|
|
@ -264,6 +264,11 @@ Uncomment line below to generate index.
|
|
|
|
|
<!ENTITY colorecho SYSTEM "color-echo.sh">
|
|
|
|
|
<!ENTITY selfsource SYSTEM "self-source.sh">
|
|
|
|
|
<!ENTITY arrowdetect SYSTEM "arrow-detect.sh">
|
|
|
|
|
<!ENTITY paragraphspace SYSTEM "paragraph-space.sh">
|
|
|
|
|
<!ENTITY brokenlink SYSTEM "broken-link.sh">
|
|
|
|
|
<!ENTITY continuenex SYSTEM "continue-n.example">
|
|
|
|
|
<!ENTITY pickcard SYSTEM "pick-card.sh">
|
|
|
|
|
<!ENTITY evalex SYSTEM "eval.example">
|
|
|
|
|
<!ENTITY namesdata SYSTEM "names.data">
|
|
|
|
|
<!ENTITY gen0data SYSTEM "gen0">
|
|
|
|
|
<!ENTITY bashrc SYSTEM "bashrc">
|
|
|
|
@ -284,8 +289,8 @@ Uncomment line below to generate index.
|
|
|
|
|
</affiliation>
|
|
|
|
|
</author>
|
|
|
|
|
|
|
|
|
|
<releaseinfo>1.6</releaseinfo>
|
|
|
|
|
<pubdate>29 September 2002</pubdate>
|
|
|
|
|
<releaseinfo>1.7</releaseinfo>
|
|
|
|
|
<pubdate>05 January 2003</pubdate>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<revhistory>
|
|
|
|
@ -382,6 +387,14 @@ Uncomment line below to generate index.
|
|
|
|
|
more script added.</revremark>
|
|
|
|
|
</revision>
|
|
|
|
|
|
|
|
|
|
<revision>
|
|
|
|
|
<revnumber>1.7</revnumber>
|
|
|
|
|
<date>05 January 2003</date>
|
|
|
|
|
<authorinitials>mc</authorinitials>
|
|
|
|
|
<revremark>'COCONUT' release: a couple of bugfixes, more material, one
|
|
|
|
|
more script.</revremark>
|
|
|
|
|
</revision>
|
|
|
|
|
|
|
|
|
|
</revhistory>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -402,7 +415,7 @@ Uncomment line below to generate index.
|
|
|
|
|
linkend="bzipref">bzip2-ed</link> <quote>tarball</quote>
|
|
|
|
|
including both the SGML source and
|
|
|
|
|
rendered HTML, may be downloaded from <ulink
|
|
|
|
|
url="http://personal.riverusers.com/~thegrendel/abs-guide-1.6.tar.bz2">
|
|
|
|
|
url="http://personal.riverusers.com/~thegrendel/abs-guide-1.7.tar.bz2">
|
|
|
|
|
the author's home site</ulink>. See the <ulink
|
|
|
|
|
url="http://personal.riverusers.com/~thegrendel/Change.log">change
|
|
|
|
|
log</ulink> for a revision history.</para>
|
|
|
|
@ -442,7 +455,7 @@ Uncomment line below to generate index.
|
|
|
|
|
<title>Why Shell Programming?</title>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<para>A working knowledge of shell scripting is essential to everyone
|
|
|
|
|
<para>A working knowledge of shell scripting is essential to anyone
|
|
|
|
|
wishing to become reasonably adept at system administration,
|
|
|
|
|
even if they do not anticipate ever having to actually write a
|
|
|
|
|
script. Consider that as a Linux machine boots up, it executes the
|
|
|
|
@ -532,7 +545,7 @@ Uncomment line below to generate index.
|
|
|
|
|
</itemizedlist></para>
|
|
|
|
|
|
|
|
|
|
<para>If any of the above applies, consider a more powerful scripting
|
|
|
|
|
language, perhaps Perl, Tcl, Python, or possibly a high-level
|
|
|
|
|
language, perhaps Perl, Tcl, Python, Ruby, or possibly a high-level
|
|
|
|
|
compiled language such as C, C++, or Java. Even then, prototyping
|
|
|
|
|
the application as a shell script might still be a useful
|
|
|
|
|
development step.</para>
|
|
|
|
@ -553,7 +566,7 @@ Uncomment line below to generate index.
|
|
|
|
|
is not recommended due to certain inherent problems, as pointed out
|
|
|
|
|
in an October, 1993 <ulink
|
|
|
|
|
url="http://www.etext.org/Quartz/computer/unix/csh.harmful.gz">Usenet
|
|
|
|
|
posting</ulink> by Tom Christiansen).
|
|
|
|
|
post</ulink> by Tom Christiansen).
|
|
|
|
|
</para>
|
|
|
|
|
|
|
|
|
|
<para>What follows is a tutorial on shell scripting. It relies
|
|
|
|
@ -704,8 +717,8 @@ exit $WHATEVER # Doesn't matter. The script will not exit here.</programlisting
|
|
|
|
|
Using <userinput>#!/bin/sh</userinput>, the default Bourne Shell
|
|
|
|
|
in most commercial variants of UNIX, makes the script <link
|
|
|
|
|
linkend="portabilityissues">portable</link> to non-Linux machines,
|
|
|
|
|
though you may have to sacrifice a few Bash-specific features
|
|
|
|
|
(the script will conform to the
|
|
|
|
|
though you may have to sacrifice a few Bash-specific features.
|
|
|
|
|
The script will, however, conform to the
|
|
|
|
|
<acronym>POSIX</acronym>
|
|
|
|
|
<footnote><para><emphasis role="strong">P</emphasis>ortable
|
|
|
|
|
<emphasis role="strong">O</emphasis>perating
|
|
|
|
@ -713,36 +726,39 @@ exit $WHATEVER # Doesn't matter. The script will not exit here.</programlisting
|
|
|
|
|
role="bold">I</emphasis>nterface, an attempt to
|
|
|
|
|
standardize UNI<emphasis role="strong">X</emphasis>-like
|
|
|
|
|
OSes.</para></footnote>
|
|
|
|
|
<command>sh</command> standard).</para>
|
|
|
|
|
<command>sh</command> standard.</para>
|
|
|
|
|
|
|
|
|
|
<para>Note that the path given at the <quote>sha-bang</quote> must
|
|
|
|
|
be correct, otherwise an error message, usually <quote>Command not
|
|
|
|
|
found</quote> will be the only result of running the script.</para>
|
|
|
|
|
be correct, otherwise an error message -- usually <quote>Command
|
|
|
|
|
not found</quote> -- will be the only result of running the
|
|
|
|
|
script.</para>
|
|
|
|
|
|
|
|
|
|
<para><token>#!</token> can be omitted if the script consists only
|
|
|
|
|
of a set of generic system commands, using no internal
|
|
|
|
|
shell directives. The second example, above, requires the
|
|
|
|
|
initial <token>#!</token>, since the variable assignment line,
|
|
|
|
|
<userinput>lines=50</userinput>, uses a shell-specific construct.
|
|
|
|
|
Note that <userinput>#!/bin/sh</userinput> invokes the default
|
|
|
|
|
Note again that <userinput>#!/bin/sh</userinput> invokes the default
|
|
|
|
|
shell interpreter, which defaults to <filename>/bin/bash</filename>
|
|
|
|
|
on a Linux machine.</para>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<important><para>This tutorial encourages a modular approach
|
|
|
|
|
<important>
|
|
|
|
|
<para>This tutorial encourages a modular approach
|
|
|
|
|
to constructing a script. Make note of and collect
|
|
|
|
|
<quote>boilerplate</quote> code snippets that might be useful
|
|
|
|
|
in future scripts. Eventually you can build a quite extensive
|
|
|
|
|
library of nifty routines. As an example, the following script
|
|
|
|
|
prolog tests whether the script has been invoked with the correct
|
|
|
|
|
number of parameters.
|
|
|
|
|
number of parameters.</para>
|
|
|
|
|
|
|
|
|
|
<programlisting>if [ $# -ne Number_of_expected args ]
|
|
|
|
|
<para><programlisting>if [ $# -ne Number_of_expected args ]
|
|
|
|
|
then
|
|
|
|
|
echo "Usage: `basename $0` whatever"
|
|
|
|
|
exit $WRONG_ARGS
|
|
|
|
|
fi</programlisting>
|
|
|
|
|
</para></important>
|
|
|
|
|
</para>
|
|
|
|
|
</important>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<sect1 id="invoking">
|
|
|
|
@ -755,7 +771,7 @@ fi</programlisting>
|
|
|
|
|
script may therefore fail to execute.</para></footnote>
|
|
|
|
|
|
|
|
|
|
or alternatively <userinput>bash scriptname</userinput>. (Not
|
|
|
|
|
recommended is using <userinput>sh <scriptname</userinput>,
|
|
|
|
|
recommended is using <userinput>sh <scriptname></userinput>,
|
|
|
|
|
since this effectively disables reading from
|
|
|
|
|
<filename>stdin</filename> within the script.) Much more
|
|
|
|
|
convenient is to make the script itself directly executable with
|
|
|
|
@ -2994,6 +3010,9 @@ arch=$(uname -m)</programlisting></para>
|
|
|
|
|
After $9, the arguments must be enclosed in brackets,
|
|
|
|
|
for example, ${10}, ${11}, ${12}.</para>
|
|
|
|
|
|
|
|
|
|
<para>The special variables <link linkend="appref">$* and $@</link>
|
|
|
|
|
denote <emphasis>all</emphasis> the positional parameters.</para>
|
|
|
|
|
|
|
|
|
|
<example id="ex17">
|
|
|
|
|
<title>Positional Parameters</title>
|
|
|
|
|
<programlisting>&ex17;</programlisting>
|
|
|
|
@ -4252,9 +4271,14 @@ home=/home/bozo
|
|
|
|
|
</varlistentry>
|
|
|
|
|
</variablelist>
|
|
|
|
|
|
|
|
|
|
<example id="brokenlink">
|
|
|
|
|
<title>Testing for broken links</title>
|
|
|
|
|
<programlisting>&brokenlink;</programlisting>
|
|
|
|
|
</example>
|
|
|
|
|
|
|
|
|
|
<para><xref linkend="cookies">, <xref linkend="bingrep">,
|
|
|
|
|
<xref linkend="fileinfo">, <xref linkend="ramdisk">, and <xref
|
|
|
|
|
linkend="mailformat"> illustrate uses of the file test
|
|
|
|
|
linkend="mailformat"> also illustrate uses of the file test
|
|
|
|
|
operators.</para>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -5844,7 +5868,8 @@ echo "Last command argument processed = $last_cmd_arg"
|
|
|
|
|
<secondary>pipe</secondary>
|
|
|
|
|
</indexterm>
|
|
|
|
|
<listitem>
|
|
|
|
|
<para>Exit status of last executed <link
|
|
|
|
|
<para>Exit status of last executed
|
|
|
|
|
<emphasis>foreground</emphasis> <link
|
|
|
|
|
linkend="piperef">pipe</link>. Interestingly enough,
|
|
|
|
|
this does not give the same result as the <link
|
|
|
|
|
linkend="exitstatusref">exit status</link> of the last
|
|
|
|
@ -5867,6 +5892,36 @@ echo "Last command argument processed = $last_cmd_arg"
|
|
|
|
|
</screen>
|
|
|
|
|
</para>
|
|
|
|
|
|
|
|
|
|
<caution>
|
|
|
|
|
|
|
|
|
|
<para>
|
|
|
|
|
The <varname>$PIPESTATUS</varname> variable
|
|
|
|
|
may contain an erroneous <errorcode>0</errorcode> value
|
|
|
|
|
in a login shell.
|
|
|
|
|
</para>
|
|
|
|
|
|
|
|
|
|
<para>
|
|
|
|
|
<screen>
|
|
|
|
|
<prompt>tcsh% </prompt><userinput>bash</userinput>
|
|
|
|
|
|
|
|
|
|
<prompt>bash$ </prompt><userinput>who | grep nobody | sort</userinput>
|
|
|
|
|
<prompt>bash$ </prompt><userinput>echo ${PIPESTATUS[*]}</userinput>
|
|
|
|
|
<computeroutput>0</computeroutput>
|
|
|
|
|
</screen>
|
|
|
|
|
</para>
|
|
|
|
|
|
|
|
|
|
<para>
|
|
|
|
|
The above lines contained in a script would produce the expected
|
|
|
|
|
<computeroutput>0 1 0</computeroutput> output.
|
|
|
|
|
</para>
|
|
|
|
|
|
|
|
|
|
<para>
|
|
|
|
|
Thank you, Wayne Pollock for pointing this out and supplying the
|
|
|
|
|
above example.
|
|
|
|
|
</para>
|
|
|
|
|
|
|
|
|
|
</caution>
|
|
|
|
|
|
|
|
|
|
</listitem>
|
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
|
@ -6547,7 +6602,8 @@ echo $_ # :</programlisting></example>
|
|
|
|
|
<secondary>expr</secondary>
|
|
|
|
|
</indexterm>
|
|
|
|
|
|
|
|
|
|
<listitem><para>
|
|
|
|
|
<listitem>
|
|
|
|
|
<para>
|
|
|
|
|
<programlisting>stringZ=abcABC123ABCabc
|
|
|
|
|
|
|
|
|
|
echo ${#stringZ} # 15
|
|
|
|
@ -6555,10 +6611,16 @@ echo `expr length $stringZ` # 15
|
|
|
|
|
echo `expr "$stringZ" : '.*'` # 15</programlisting>
|
|
|
|
|
</para>
|
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
|
|
</variablelist>
|
|
|
|
|
|
|
|
|
|
<example id="paragraphspace">
|
|
|
|
|
<title>Inserting a blank line between paragraphs in a text file</title>
|
|
|
|
|
<programlisting>¶graphspace;</programlisting>
|
|
|
|
|
</example>
|
|
|
|
|
|
|
|
|
|
<variablelist id="lengthsubstring">
|
|
|
|
|
<title>Length of Matching Substring at Beginning of String</title>
|
|
|
|
|
|
|
|
|
@ -7600,10 +7662,37 @@ echo "number = $number" # number = 0
|
|
|
|
|
<programlisting>&ex21;</programlisting>
|
|
|
|
|
</example>
|
|
|
|
|
|
|
|
|
|
<para>Just how random is RANDOM? The best way to test this is
|
|
|
|
|
<example id="pickcard">
|
|
|
|
|
<title>Picking a random card from a deck</title>
|
|
|
|
|
<programlisting>&pickcard;</programlisting>
|
|
|
|
|
</example>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<note>
|
|
|
|
|
|
|
|
|
|
<para>
|
|
|
|
|
<emphasis>Jipe</emphasis> points out another set of techniques
|
|
|
|
|
for generating random numbers within a range.
|
|
|
|
|
</para>
|
|
|
|
|
|
|
|
|
|
<para>
|
|
|
|
|
<programlisting># Generate random number between 6 and 30.
|
|
|
|
|
rnumber=$((RANDOM%25+6))
|
|
|
|
|
|
|
|
|
|
# Generate random number in the same 6 - 30 range,
|
|
|
|
|
#+ but the number must be evenly divisible by 3.
|
|
|
|
|
rnumber=$(((RANDOM%30/3+1)*3))
|
|
|
|
|
|
|
|
|
|
# Exercise: Try to figure out the pattern here.</programlisting>
|
|
|
|
|
</para>
|
|
|
|
|
|
|
|
|
|
</note>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<para>Just how random is $RANDOM? The best way to test this is
|
|
|
|
|
to write a script that tracks the distribution of
|
|
|
|
|
<quote>random</quote> numbers generated by RANDOM. Let's roll
|
|
|
|
|
a RANDOM die a few times...</para>
|
|
|
|
|
<quote>random</quote> numbers generated by $RANDOM. Let's roll
|
|
|
|
|
a $RANDOM die a few times...</para>
|
|
|
|
|
|
|
|
|
|
<example id="randomtest">
|
|
|
|
|
<title>Rolling the die with RANDOM</title>
|
|
|
|
@ -8139,6 +8228,11 @@ echo "number = $number" # number = 0
|
|
|
|
|
<programlisting>&continuelevels;</programlisting>
|
|
|
|
|
</example>
|
|
|
|
|
|
|
|
|
|
<example id="continuenex">
|
|
|
|
|
<title>Using <quote>continue N</quote> in an actual task</title>
|
|
|
|
|
<programlisting>&continuenex;</programlisting>
|
|
|
|
|
</example>
|
|
|
|
|
|
|
|
|
|
<caution><para>The <command>continue N</command> construct is
|
|
|
|
|
difficult to understand and tricky to use in any meaningful
|
|
|
|
|
context. It is probably best avoided.</para></caution>
|
|
|
|
@ -8860,6 +8954,17 @@ done</programlisting></para>
|
|
|
|
|
<programlisting>&rot14;</programlisting>
|
|
|
|
|
</example>
|
|
|
|
|
|
|
|
|
|
<para>Rory Winston contributed the following instance of how
|
|
|
|
|
useful <command>eval</command> can be.</para>
|
|
|
|
|
|
|
|
|
|
<example id="evalex">
|
|
|
|
|
<title>Using <command>eval</command> to force variable
|
|
|
|
|
substitution in a Perl script</title>
|
|
|
|
|
<programlisting>&evalex;</programlisting>
|
|
|
|
|
</example>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<caution><para>The <command>eval</command> command can be
|
|
|
|
|
risky, and normally should be avoided when there
|
|
|
|
|
exists a reasonable alternative. An <userinput>eval
|
|
|
|
@ -14495,8 +14600,8 @@ LIMIT_STRING
|
|
|
|
|
<listitem>
|
|
|
|
|
<para>[UNIX borrows an idea here from the plumbing trade.]</para>
|
|
|
|
|
<para>This is a redirection operator, but with a difference. Like the
|
|
|
|
|
plumber's <emphasis>tee</emphasis>, it permits <quote>siponing
|
|
|
|
|
off</quote> the output of a command
|
|
|
|
|
plumber's <quote>tee,</quote> it permits <quote>siponing
|
|
|
|
|
off</quote> <emphasis>to a file </emphasis>the output of a command
|
|
|
|
|
or commands within a pipe, but without affecting the result. This is
|
|
|
|
|
useful for printing an ongoing process to a file or paper, perhaps to
|
|
|
|
|
keep track of it for debugging purposes.</para>
|
|
|
|
@ -17248,16 +17353,45 @@ then
|
|
|
|
|
<secondary>ulimit</secondary>
|
|
|
|
|
</indexterm>
|
|
|
|
|
<listitem>
|
|
|
|
|
<para>Sets an <emphasis>upper limit</emphasis> on system
|
|
|
|
|
resources. Usually invoked with the <option>-f</option>
|
|
|
|
|
option, which sets a limit on file size (<command>ulimit
|
|
|
|
|
-f 1000</command> limits files to 1 meg maximum). The
|
|
|
|
|
<option>-t</option> option limits the coredump size
|
|
|
|
|
(<command>ulimit -c 0</command> eliminates coredumps).
|
|
|
|
|
|
|
|
|
|
<para>Sets an <emphasis>upper limit</emphasis> on use
|
|
|
|
|
of system resources. Usually invoked with the
|
|
|
|
|
<option>-f</option> option, which sets a limit on file size
|
|
|
|
|
(<command>ulimit -f 1000</command> limits files to 1 meg
|
|
|
|
|
maximum). The <option>-t</option> option limits the coredump
|
|
|
|
|
size (<command>ulimit -c 0</command> eliminates coredumps).
|
|
|
|
|
Normally, the value of <command>ulimit</command>
|
|
|
|
|
would be set in <filename>/etc/profile</filename>
|
|
|
|
|
and/or <filename>~/.bash_profile</filename> (see <xref
|
|
|
|
|
linkend="files">).</para>
|
|
|
|
|
|
|
|
|
|
<important>
|
|
|
|
|
|
|
|
|
|
<para>Judicious use of <command>ulimit</command> can
|
|
|
|
|
protect a system against the dreaded <emphasis>fork
|
|
|
|
|
bomb</emphasis>.</para>
|
|
|
|
|
|
|
|
|
|
<para>
|
|
|
|
|
<programlisting>#!/bin/bash
|
|
|
|
|
|
|
|
|
|
while 1 # Endless loop.
|
|
|
|
|
do
|
|
|
|
|
$0 & # This script invokes itself . . .
|
|
|
|
|
#+ forks an infinite number of times . . .
|
|
|
|
|
#+ until the system freezes up because all resources exhausted.
|
|
|
|
|
done # This is the notorious <quote>sorcerer's appentice</quote> scenario.
|
|
|
|
|
|
|
|
|
|
exit 0 # Will not exit here, because this script will never terminate.</programlisting>
|
|
|
|
|
</para>
|
|
|
|
|
|
|
|
|
|
<para>A <command>ulimit -Hu XX</command> (where
|
|
|
|
|
<emphasis>XX</emphasis> is the user process limit) in
|
|
|
|
|
<filename>/etc/profile</filename> would abort
|
|
|
|
|
this script when it exceeds the preset limit.
|
|
|
|
|
</para>
|
|
|
|
|
|
|
|
|
|
</important>
|
|
|
|
|
|
|
|
|
|
</listitem>
|
|
|
|
|
</varlistentry>
|
|
|
|
|
|
|
|
|
@ -20256,9 +20390,10 @@ false && ( true || echo false ) # (nothing echoed)
|
|
|
|
|
# Thanks, S.C.</programlisting>
|
|
|
|
|
</para>
|
|
|
|
|
|
|
|
|
|
<para>See <xref linkend="daysbetween"> for an illustration of using
|
|
|
|
|
an <userinput>and / or list</userinput> to test variables.</para>
|
|
|
|
|
|
|
|
|
|
<para>See <xref linkend="daysbetween"> and <xref
|
|
|
|
|
linkend="brokenlink"> for illustrations of using an <userinput>and
|
|
|
|
|
/ or list</userinput> to test variables.</para>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</chapter> <!-- List Constructs -->
|
|
|
|
|
|
|
|
|
@ -20857,9 +20992,16 @@ ln -s /dev/null ~/.netscape/cookies
|
|
|
|
|
<title>Debugging</title>
|
|
|
|
|
|
|
|
|
|
<para>The Bash shell contains no debugger, nor even any
|
|
|
|
|
debugging-specific commands or constructs. Syntax errors or
|
|
|
|
|
outright typos in the script generate cryptic error messages that
|
|
|
|
|
are often of no help in debugging a non-functional script.</para>
|
|
|
|
|
debugging-specific commands or constructs.
|
|
|
|
|
|
|
|
|
|
<footnote><para>Rocky Bernstein's
|
|
|
|
|
<ulink
|
|
|
|
|
url="http://bashdb.sourceforge.net"> Bash debugger</ulink>
|
|
|
|
|
partially makes up for this lack.</para></footnote>
|
|
|
|
|
|
|
|
|
|
Syntax errors or outright typos in the script generate cryptic
|
|
|
|
|
error messages that are often of no help in debugging a
|
|
|
|
|
non-functional script.</para>
|
|
|
|
|
|
|
|
|
|
<example id="ex74">
|
|
|
|
|
<title>A buggy script</title>
|
|
|
|
@ -22946,8 +23088,9 @@ fi</programlisting>
|
|
|
|
|
were Gabor Kiss, Leopold Toetsch, Peter Tillier, Marcus Berglof,
|
|
|
|
|
Tony Richardson, Nick Drage (script ideas!), Rich Bartell, Jess
|
|
|
|
|
Thrysoee, Adam Lazur, Bram Moolenaar, Baris Cicek, Greg Keraunen,
|
|
|
|
|
Keith Matthews, Sandro Magi, and David Lawyer (himself an author
|
|
|
|
|
of 4 HOWTOs).</para>
|
|
|
|
|
Keith Matthews, Sandro Magi, Albert Reiner, Dim Segebart, Rory
|
|
|
|
|
Winston, Lee Bigelow, Wayne Pollock, <quote>jipe</quote>, and
|
|
|
|
|
David Lawyer (himself an author of 4 HOWTOs).</para>
|
|
|
|
|
|
|
|
|
|
<para>My gratitude to <ulink url="mailto:chet@po.cwru.edu">Chet
|
|
|
|
|
Ramey</ulink> and Brian Fox for writing <command>Bash</command>,
|
|
|
|
@ -23499,6 +23642,15 @@ fi</programlisting>
|
|
|
|
|
Hohensee</ulink> has written the <ulink
|
|
|
|
|
url="ftp://ftp.gwdg.de/pub/linux/install/clienux/interim/osimpa.tgz">
|
|
|
|
|
osimpa</ulink> i386 assembler entirely as Bash scripts.</para>
|
|
|
|
|
</abstract>
|
|
|
|
|
</biblioentry>
|
|
|
|
|
|
|
|
|
|
<biblioentry>
|
|
|
|
|
<abstract>
|
|
|
|
|
<para>Rocky Bernstein is in the process of developing a
|
|
|
|
|
<quote>full-fledged</quote> <ulink
|
|
|
|
|
url="http://bashdb.sourceforge.net"> debugger</ulink> for
|
|
|
|
|
Bash.</para>
|
|
|
|
|
<para>---</para>
|
|
|
|
|
</abstract>
|
|
|
|
|
</biblioentry>
|
|
|
|
|