1062 lines
17 KiB
HTML
1062 lines
17 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
|
<HTML
|
|
><HEAD
|
|
><TITLE
|
|
>Starting Off With a Sha-Bang</TITLE
|
|
><META
|
|
NAME="GENERATOR"
|
|
CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK
|
|
REL="HOME"
|
|
TITLE="Advanced Bash-Scripting Guide"
|
|
HREF="index.html"><LINK
|
|
REL="UP"
|
|
TITLE="Introduction"
|
|
HREF="part1.html"><LINK
|
|
REL="PREVIOUS"
|
|
TITLE="Shell Programming!"
|
|
HREF="why-shell.html"><LINK
|
|
REL="NEXT"
|
|
TITLE="Invoking the script"
|
|
HREF="invoking.html"></HEAD
|
|
><BODY
|
|
CLASS="CHAPTER"
|
|
BGCOLOR="#FFFFFF"
|
|
TEXT="#000000"
|
|
LINK="#0000FF"
|
|
VLINK="#840084"
|
|
ALINK="#0000FF"
|
|
><DIV
|
|
CLASS="NAVHEADER"
|
|
><TABLE
|
|
SUMMARY="Header navigation table"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
CELLPADDING="0"
|
|
CELLSPACING="0"
|
|
><TR
|
|
><TH
|
|
COLSPAN="3"
|
|
ALIGN="center"
|
|
>Advanced Bash-Scripting Guide: </TH
|
|
></TR
|
|
><TR
|
|
><TD
|
|
WIDTH="10%"
|
|
ALIGN="left"
|
|
VALIGN="bottom"
|
|
><A
|
|
HREF="why-shell.html"
|
|
ACCESSKEY="P"
|
|
>Prev</A
|
|
></TD
|
|
><TD
|
|
WIDTH="80%"
|
|
ALIGN="center"
|
|
VALIGN="bottom"
|
|
></TD
|
|
><TD
|
|
WIDTH="10%"
|
|
ALIGN="right"
|
|
VALIGN="bottom"
|
|
><A
|
|
HREF="invoking.html"
|
|
ACCESSKEY="N"
|
|
>Next</A
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><HR
|
|
ALIGN="LEFT"
|
|
WIDTH="100%"></DIV
|
|
><DIV
|
|
CLASS="CHAPTER"
|
|
><H1
|
|
><A
|
|
NAME="SHA-BANG"
|
|
></A
|
|
>Chapter 2. Starting Off With a Sha-Bang</H1
|
|
><TABLE
|
|
BORDER="0"
|
|
WIDTH="100%"
|
|
CELLSPACING="0"
|
|
CELLPADDING="0"
|
|
CLASS="EPIGRAPH"
|
|
><TR
|
|
><TD
|
|
WIDTH="45%"
|
|
> </TD
|
|
><TD
|
|
WIDTH="45%"
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
><I
|
|
><P
|
|
><I
|
|
>Shell programming is a 1950s juke box . . .</I
|
|
></P
|
|
><P
|
|
><I
|
|
>--Larry Wall</I
|
|
></P
|
|
></I
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><DIV
|
|
CLASS="TOC"
|
|
><DL
|
|
><DT
|
|
><B
|
|
>Table of Contents</B
|
|
></DT
|
|
><DT
|
|
>2.1. <A
|
|
HREF="invoking.html"
|
|
>Invoking the script</A
|
|
></DT
|
|
><DT
|
|
>2.2. <A
|
|
HREF="prelimexer.html"
|
|
>Preliminary Exercises</A
|
|
></DT
|
|
></DL
|
|
></DIV
|
|
><P
|
|
>In the simplest case, a script is nothing more than a list
|
|
of system commands stored in a file. At the very least, this saves
|
|
the effort of retyping that particular sequence of commands each
|
|
time it is invoked.</P
|
|
><DIV
|
|
CLASS="EXAMPLE"
|
|
><A
|
|
NAME="EX1"
|
|
></A
|
|
><P
|
|
><B
|
|
>Example 2-1. <I
|
|
CLASS="FIRSTTERM"
|
|
>cleanup</I
|
|
>: A script to clean up log
|
|
files in /var/log </B
|
|
></P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
># Cleanup
|
|
# Run as root, of course.
|
|
|
|
cd /var/log
|
|
cat /dev/null > messages
|
|
cat /dev/null > wtmp
|
|
echo "Log files cleaned up."</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
><P
|
|
>There is nothing unusual here, only a set of commands that
|
|
could just as easily have been invoked one by one from the
|
|
command-line on the console or in a terminal window.
|
|
The advantages of placing the commands in a script go far beyond
|
|
not having to retype them time and again. The script becomes a
|
|
<I
|
|
CLASS="FIRSTTERM"
|
|
>program</I
|
|
> -- a <EM
|
|
>tool</EM
|
|
> --
|
|
and it can easily be modified or customized for a particular
|
|
application.</P
|
|
><DIV
|
|
CLASS="EXAMPLE"
|
|
><A
|
|
NAME="EX1A"
|
|
></A
|
|
><P
|
|
><B
|
|
>Example 2-2. <I
|
|
CLASS="FIRSTTERM"
|
|
>cleanup</I
|
|
>: An improved clean-up
|
|
script</B
|
|
></P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>#!/bin/bash
|
|
# Proper header for a Bash script.
|
|
|
|
# Cleanup, version 2
|
|
|
|
# Run as root, of course.
|
|
# Insert code here to print error message and exit if not root.
|
|
|
|
LOG_DIR=/var/log
|
|
# Variables are better than hard-coded values.
|
|
cd $LOG_DIR
|
|
|
|
cat /dev/null > messages
|
|
cat /dev/null > wtmp
|
|
|
|
|
|
echo "Logs cleaned up."
|
|
|
|
exit # The right and proper method of "exiting" from a script.
|
|
# A bare "exit" (no parameter) returns the exit status
|
|
#+ of the preceding command. </PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
><P
|
|
>Now <EM
|
|
>that's</EM
|
|
> beginning to look like a real
|
|
script. But we can go even farther . . .</P
|
|
><DIV
|
|
CLASS="EXAMPLE"
|
|
><A
|
|
NAME="EX2"
|
|
></A
|
|
><P
|
|
><B
|
|
>Example 2-3. <I
|
|
CLASS="FIRSTTERM"
|
|
>cleanup</I
|
|
>: An enhanced
|
|
and generalized version of above scripts.</B
|
|
></P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>#!/bin/bash
|
|
# Cleanup, version 3
|
|
|
|
# Warning:
|
|
# -------
|
|
# This script uses quite a number of features that will be explained
|
|
#+ later on.
|
|
# By the time you've finished the first half of the book,
|
|
#+ there should be nothing mysterious about it.
|
|
|
|
|
|
|
|
LOG_DIR=/var/log
|
|
ROOT_UID=0 # Only users with $UID 0 have root privileges.
|
|
LINES=50 # Default number of lines saved.
|
|
E_XCD=86 # Can't change directory?
|
|
E_NOTROOT=87 # Non-root exit error.
|
|
|
|
|
|
# Run as root, of course.
|
|
if [ "$UID" -ne "$ROOT_UID" ]
|
|
then
|
|
echo "Must be root to run this script."
|
|
exit $E_NOTROOT
|
|
fi
|
|
|
|
if [ -n "$1" ]
|
|
# Test whether command-line argument is present (non-empty).
|
|
then
|
|
lines=$1
|
|
else
|
|
lines=$LINES # Default, if not specified on command-line.
|
|
fi
|
|
|
|
|
|
# Stephane Chazelas suggests the following,
|
|
#+ as a better way of checking command-line arguments,
|
|
#+ but this is still a bit advanced for this stage of the tutorial.
|
|
#
|
|
# E_WRONGARGS=85 # Non-numerical argument (bad argument format).
|
|
#
|
|
# case "$1" in
|
|
# "" ) lines=50;;
|
|
# *[!0-9]*) echo "Usage: `basename $0` lines-to-cleanup";
|
|
# exit $E_WRONGARGS;;
|
|
# * ) lines=$1;;
|
|
# esac
|
|
#
|
|
#* Skip ahead to "Loops" chapter to decipher all this.
|
|
|
|
|
|
cd $LOG_DIR
|
|
|
|
if [ `pwd` != "$LOG_DIR" ] # or if [ "$PWD" != "$LOG_DIR" ]
|
|
# Not in /var/log?
|
|
then
|
|
echo "Can't change to $LOG_DIR."
|
|
exit $E_XCD
|
|
fi # Doublecheck if in right directory before messing with log file.
|
|
|
|
# Far more efficient is:
|
|
#
|
|
# cd /var/log || {
|
|
# echo "Cannot change to necessary directory." >&2
|
|
# exit $E_XCD;
|
|
# }
|
|
|
|
|
|
|
|
|
|
tail -n $lines messages > mesg.temp # Save last section of message log file.
|
|
mv mesg.temp messages # Rename it as system log file.
|
|
|
|
|
|
# cat /dev/null > messages
|
|
#* No longer needed, as the above method is safer.
|
|
|
|
cat /dev/null > wtmp # ': > wtmp' and '> wtmp' have the same effect.
|
|
echo "Log files cleaned up."
|
|
# Note that there are other log files in /var/log not affected
|
|
#+ by this script.
|
|
|
|
exit 0
|
|
# A zero return value from the script upon exit indicates success
|
|
#+ to the shell.</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
><P
|
|
>Since you may not wish to wipe out the entire system log,
|
|
this version of the script keeps the last section of the message
|
|
log intact. You will constantly discover ways of fine-tuning
|
|
previously written scripts for increased effectiveness.</P
|
|
><P
|
|
><A
|
|
NAME="SHABANGREF"
|
|
></A
|
|
>* * *</P
|
|
><P
|
|
><A
|
|
NAME="MAGNUMREF"
|
|
></A
|
|
>The
|
|
<I
|
|
CLASS="FIRSTTERM"
|
|
> sha-bang</I
|
|
>
|
|
(<SPAN
|
|
CLASS="TOKEN"
|
|
> #!</SPAN
|
|
>)
|
|
|
|
<A
|
|
NAME="AEN205"
|
|
HREF="#FTN.AEN205"
|
|
><SPAN
|
|
CLASS="footnote"
|
|
>[1]</SPAN
|
|
></A
|
|
>
|
|
|
|
at the head of a script tells your system that this file is a set
|
|
of commands to be fed to the command interpreter indicated. The
|
|
<SPAN
|
|
CLASS="TOKEN"
|
|
>#!</SPAN
|
|
> is actually a two-byte
|
|
|
|
<A
|
|
NAME="AEN214"
|
|
HREF="#FTN.AEN214"
|
|
><SPAN
|
|
CLASS="footnote"
|
|
>[2]</SPAN
|
|
></A
|
|
>
|
|
|
|
|
|
<I
|
|
CLASS="FIRSTTERM"
|
|
>magic number</I
|
|
>, a special marker that
|
|
designates a file type, or in this case an executable shell
|
|
script (type <TT
|
|
CLASS="USERINPUT"
|
|
><B
|
|
>man magic</B
|
|
></TT
|
|
> for more
|
|
details on this fascinating topic). Immediately following
|
|
the <I
|
|
CLASS="FIRSTTERM"
|
|
>sha-bang</I
|
|
> is a <I
|
|
CLASS="FIRSTTERM"
|
|
>path
|
|
name</I
|
|
>. This is the path to the program that interprets
|
|
the commands in the script, whether it be a shell, a programming
|
|
language, or a utility. This command interpreter then executes
|
|
the commands in the script, starting at the top (the line
|
|
following the <I
|
|
CLASS="FIRSTTERM"
|
|
>sha-bang</I
|
|
> line), and ignoring
|
|
comments.
|
|
|
|
<A
|
|
NAME="AEN226"
|
|
HREF="#FTN.AEN226"
|
|
><SPAN
|
|
CLASS="footnote"
|
|
>[3]</SPAN
|
|
></A
|
|
>
|
|
|
|
</P
|
|
><P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>#!/bin/sh
|
|
#!/bin/bash
|
|
#!/usr/bin/perl
|
|
#!/usr/bin/tcl
|
|
#!/bin/sed -f
|
|
#!/bin/awk -f</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></P
|
|
><P
|
|
>Each of the above script header lines calls a different command
|
|
interpreter, be it <TT
|
|
CLASS="FILENAME"
|
|
>/bin/sh</TT
|
|
>, the default shell
|
|
(<B
|
|
CLASS="COMMAND"
|
|
>bash</B
|
|
> in a Linux system) or otherwise.
|
|
|
|
<A
|
|
NAME="AEN242"
|
|
HREF="#FTN.AEN242"
|
|
><SPAN
|
|
CLASS="footnote"
|
|
>[4]</SPAN
|
|
></A
|
|
>
|
|
|
|
Using <TT
|
|
CLASS="USERINPUT"
|
|
><B
|
|
>#!/bin/sh</B
|
|
></TT
|
|
>, the default Bourne shell
|
|
in most commercial variants of UNIX, makes the script <A
|
|
HREF="portabilityissues.html"
|
|
>portable</A
|
|
> to non-Linux machines,
|
|
though you <A
|
|
HREF="gotchas.html#BINSH"
|
|
>sacrifice Bash-specific
|
|
features</A
|
|
>. The script will, however, conform to the
|
|
<SPAN
|
|
CLASS="ACRONYM"
|
|
>POSIX</SPAN
|
|
>
|
|
|
|
<A
|
|
NAME="AEN256"
|
|
HREF="#FTN.AEN256"
|
|
><SPAN
|
|
CLASS="footnote"
|
|
>[5]</SPAN
|
|
></A
|
|
>
|
|
|
|
<B
|
|
CLASS="COMMAND"
|
|
>sh</B
|
|
> standard.</P
|
|
><P
|
|
>Note that the path given at the <SPAN
|
|
CLASS="QUOTE"
|
|
>"sha-bang"</SPAN
|
|
> must
|
|
be correct, otherwise an error message -- usually <SPAN
|
|
CLASS="QUOTE"
|
|
>"Command
|
|
not found."</SPAN
|
|
> -- will be the only result of running the
|
|
script.
|
|
<A
|
|
NAME="AEN269"
|
|
HREF="#FTN.AEN269"
|
|
><SPAN
|
|
CLASS="footnote"
|
|
>[6]</SPAN
|
|
></A
|
|
>
|
|
|
|
</P
|
|
><P
|
|
><SPAN
|
|
CLASS="TOKEN"
|
|
>#!</SPAN
|
|
> 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 <SPAN
|
|
CLASS="TOKEN"
|
|
>#!</SPAN
|
|
>, since the variable assignment line,
|
|
<TT
|
|
CLASS="USERINPUT"
|
|
><B
|
|
>lines=50</B
|
|
></TT
|
|
>, uses a shell-specific construct.
|
|
<A
|
|
NAME="AEN279"
|
|
HREF="#FTN.AEN279"
|
|
><SPAN
|
|
CLASS="footnote"
|
|
>[7]</SPAN
|
|
></A
|
|
>
|
|
Note again that <TT
|
|
CLASS="USERINPUT"
|
|
><B
|
|
>#!/bin/sh</B
|
|
></TT
|
|
> invokes the default
|
|
shell interpreter, which defaults to <TT
|
|
CLASS="FILENAME"
|
|
>/bin/bash</TT
|
|
>
|
|
on a Linux machine.</P
|
|
><DIV
|
|
CLASS="TIP"
|
|
><P
|
|
></P
|
|
><TABLE
|
|
CLASS="TIP"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
><TR
|
|
><TD
|
|
WIDTH="25"
|
|
ALIGN="CENTER"
|
|
VALIGN="TOP"
|
|
><IMG
|
|
SRC="../images/tip.gif"
|
|
HSPACE="5"
|
|
ALT="Tip"></TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
><P
|
|
>This tutorial encourages a modular approach
|
|
to constructing a script. Make note of and collect
|
|
<SPAN
|
|
CLASS="QUOTE"
|
|
>"boilerplate"</SPAN
|
|
> code snippets that might be useful
|
|
in future scripts. Eventually you will build quite an 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.</P
|
|
><P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>E_WRONG_ARGS=85
|
|
script_parameters="-a -h -m -z"
|
|
# -a = all, -h = help, etc.
|
|
|
|
if [ $# -ne $Number_of_expected_args ]
|
|
then
|
|
echo "Usage: `basename $0` $script_parameters"
|
|
# `basename $0` is the script's filename.
|
|
exit $E_WRONG_ARGS
|
|
fi</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
</P
|
|
><P
|
|
>Many times, you will write a script that carries out one
|
|
particular task. The first script in this chapter is an
|
|
example. Later, it might occur to you to generalize
|
|
the script to do other, similar tasks. Replacing the literal
|
|
(<SPAN
|
|
CLASS="QUOTE"
|
|
>"hard-wired"</SPAN
|
|
>) constants by variables is a step in
|
|
that direction, as is replacing repetitive code blocks by <A
|
|
HREF="functions.html#FUNCTIONREF"
|
|
>functions</A
|
|
>.</P
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
></DIV
|
|
><H3
|
|
CLASS="FOOTNOTES"
|
|
>Notes</H3
|
|
><TABLE
|
|
BORDER="0"
|
|
CLASS="FOOTNOTES"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
WIDTH="5%"
|
|
><A
|
|
NAME="FTN.AEN205"
|
|
HREF="sha-bang.html#AEN205"
|
|
><SPAN
|
|
CLASS="footnote"
|
|
>[1]</SPAN
|
|
></A
|
|
></TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
WIDTH="95%"
|
|
><P
|
|
>More commonly seen in the literature as
|
|
<I
|
|
CLASS="FIRSTTERM"
|
|
>she-bang</I
|
|
> or <I
|
|
CLASS="FIRSTTERM"
|
|
>sh-bang</I
|
|
>.
|
|
This derives from the concatenation of the tokens
|
|
<I
|
|
CLASS="FIRSTTERM"
|
|
>sharp</I
|
|
> (<SPAN
|
|
CLASS="TOKEN"
|
|
>#</SPAN
|
|
>) and
|
|
<I
|
|
CLASS="FIRSTTERM"
|
|
>bang</I
|
|
> (<SPAN
|
|
CLASS="TOKEN"
|
|
>!</SPAN
|
|
>).</P
|
|
></TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
WIDTH="5%"
|
|
><A
|
|
NAME="FTN.AEN214"
|
|
HREF="sha-bang.html#AEN214"
|
|
><SPAN
|
|
CLASS="footnote"
|
|
>[2]</SPAN
|
|
></A
|
|
></TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
WIDTH="95%"
|
|
><P
|
|
>Some flavors of UNIX (those based on 4.2 BSD)
|
|
allegedly take a four-byte magic number, requiring
|
|
a blank after the <SPAN
|
|
CLASS="TOKEN"
|
|
>!</SPAN
|
|
> --
|
|
<TT
|
|
CLASS="USERINPUT"
|
|
><B
|
|
>#! /bin/sh</B
|
|
></TT
|
|
>. <A
|
|
HREF="http://www.in-ulm.de/~mascheck/various/shebang/#details"
|
|
TARGET="_top"
|
|
> According to Sven Mascheck</A
|
|
> this is probably a myth.</P
|
|
></TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
WIDTH="5%"
|
|
><A
|
|
NAME="FTN.AEN226"
|
|
HREF="sha-bang.html#AEN226"
|
|
><SPAN
|
|
CLASS="footnote"
|
|
>[3]</SPAN
|
|
></A
|
|
></TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
WIDTH="95%"
|
|
><P
|
|
>The <SPAN
|
|
CLASS="TOKEN"
|
|
>#!</SPAN
|
|
> line in a shell script
|
|
will be the first thing the command interpreter
|
|
(<B
|
|
CLASS="COMMAND"
|
|
>sh</B
|
|
> or <B
|
|
CLASS="COMMAND"
|
|
>bash</B
|
|
>)
|
|
sees. Since this line begins with a <SPAN
|
|
CLASS="TOKEN"
|
|
>#</SPAN
|
|
>,
|
|
it will be correctly interpreted as a comment when the
|
|
command interpreter finally executes the script. The
|
|
line has already served its purpose - calling the command
|
|
interpreter.</P
|
|
><P
|
|
>If, in fact, the script includes an
|
|
<EM
|
|
>extra</EM
|
|
> <SPAN
|
|
CLASS="TOKEN"
|
|
>#!</SPAN
|
|
> line, then
|
|
<B
|
|
CLASS="COMMAND"
|
|
>bash</B
|
|
> will interpret it as a comment.
|
|
<TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>#!/bin/bash
|
|
|
|
echo "Part 1 of script."
|
|
a=1
|
|
|
|
#!/bin/bash
|
|
# This does *not* launch a new script.
|
|
|
|
echo "Part 2 of script."
|
|
echo $a # Value of $a stays at 1.</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></P
|
|
></TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
WIDTH="5%"
|
|
><A
|
|
NAME="FTN.AEN242"
|
|
HREF="sha-bang.html#AEN242"
|
|
><SPAN
|
|
CLASS="footnote"
|
|
>[4]</SPAN
|
|
></A
|
|
></TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
WIDTH="95%"
|
|
><P
|
|
>This allows some cute tricks.</P
|
|
><P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>#!/bin/rm
|
|
# Self-deleting script.
|
|
|
|
# Nothing much seems to happen when you run this... except that the file disappears.
|
|
|
|
WHATEVER=85
|
|
|
|
echo "This line will never print (betcha!)."
|
|
|
|
exit $WHATEVER # Doesn't matter. The script will not exit here.
|
|
# Try an echo $? after script termination.
|
|
# You'll get a 0, not a 85.</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></P
|
|
><P
|
|
>Also, try starting a <TT
|
|
CLASS="FILENAME"
|
|
>README</TT
|
|
> file with a
|
|
<TT
|
|
CLASS="USERINPUT"
|
|
><B
|
|
>#!/bin/more</B
|
|
></TT
|
|
>, and making it executable.
|
|
The result is a self-listing documentation file. (A <A
|
|
HREF="here-docs.html#HEREDOCREF"
|
|
>here document</A
|
|
> using
|
|
<A
|
|
HREF="basic.html#CATREF"
|
|
>cat</A
|
|
> is possibly a better alternative
|
|
-- see <A
|
|
HREF="here-docs.html#EX71"
|
|
>Example 19-3</A
|
|
>).</P
|
|
></TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
WIDTH="5%"
|
|
><A
|
|
NAME="FTN.AEN256"
|
|
HREF="sha-bang.html#AEN256"
|
|
><SPAN
|
|
CLASS="footnote"
|
|
>[5]</SPAN
|
|
></A
|
|
></TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
WIDTH="95%"
|
|
><P
|
|
><A
|
|
NAME="POSIX2REF"
|
|
></A
|
|
><STRONG
|
|
>P</STRONG
|
|
>ortable
|
|
<STRONG
|
|
>O</STRONG
|
|
>perating
|
|
<STRONG
|
|
>S</STRONG
|
|
>ystem <EM
|
|
>I</EM
|
|
>nterface, an attempt to
|
|
standardize UNI<STRONG
|
|
>X</STRONG
|
|
>-like
|
|
OSes. The POSIX specifications are listed on the <A
|
|
HREF="http://www.opengroup.org/onlinepubs/007904975/toc.htm"
|
|
TARGET="_top"
|
|
>Open
|
|
Group site</A
|
|
>.</P
|
|
></TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
WIDTH="5%"
|
|
><A
|
|
NAME="FTN.AEN269"
|
|
HREF="sha-bang.html#AEN269"
|
|
><SPAN
|
|
CLASS="footnote"
|
|
>[6]</SPAN
|
|
></A
|
|
></TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
WIDTH="95%"
|
|
><P
|
|
>To avoid this possibility, a script may begin
|
|
with a <A
|
|
HREF="system.html#ENVV2REF"
|
|
>#!/bin/env bash</A
|
|
>
|
|
<I
|
|
CLASS="FIRSTTERM"
|
|
>sha-bang</I
|
|
> line. This may be
|
|
useful on UNIX machines where <I
|
|
CLASS="FIRSTTERM"
|
|
>bash</I
|
|
>
|
|
is not located in <TT
|
|
CLASS="FILENAME"
|
|
>/bin</TT
|
|
></P
|
|
></TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
WIDTH="5%"
|
|
><A
|
|
NAME="FTN.AEN279"
|
|
HREF="sha-bang.html#AEN279"
|
|
><SPAN
|
|
CLASS="footnote"
|
|
>[7]</SPAN
|
|
></A
|
|
></TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
WIDTH="95%"
|
|
><P
|
|
>If <I
|
|
CLASS="FIRSTTERM"
|
|
>Bash</I
|
|
> is your default
|
|
shell, then the <SPAN
|
|
CLASS="TOKEN"
|
|
>#!</SPAN
|
|
> isn't necessary at the
|
|
beginning of a script. However, if launching a script from
|
|
a different shell, such as <I
|
|
CLASS="FIRSTTERM"
|
|
>tcsh</I
|
|
>,
|
|
then you <EM
|
|
>will</EM
|
|
> need the
|
|
<SPAN
|
|
CLASS="TOKEN"
|
|
>#!</SPAN
|
|
>.</P
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><DIV
|
|
CLASS="NAVFOOTER"
|
|
><HR
|
|
ALIGN="LEFT"
|
|
WIDTH="100%"><TABLE
|
|
SUMMARY="Footer navigation table"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
CELLPADDING="0"
|
|
CELLSPACING="0"
|
|
><TR
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="left"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="why-shell.html"
|
|
ACCESSKEY="P"
|
|
>Prev</A
|
|
></TD
|
|
><TD
|
|
WIDTH="34%"
|
|
ALIGN="center"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="index.html"
|
|
ACCESSKEY="H"
|
|
>Home</A
|
|
></TD
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="right"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="invoking.html"
|
|
ACCESSKEY="N"
|
|
>Next</A
|
|
></TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="left"
|
|
VALIGN="top"
|
|
>Shell Programming!</TD
|
|
><TD
|
|
WIDTH="34%"
|
|
ALIGN="center"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="part1.html"
|
|
ACCESSKEY="U"
|
|
>Up</A
|
|
></TD
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="right"
|
|
VALIGN="top"
|
|
>Invoking the script</TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
></BODY
|
|
></HTML
|
|
> |