639 lines
12 KiB
HTML
639 lines
12 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
|
<HTML
|
|
><HEAD
|
|
><TITLE
|
|
>Of Zeros and Nulls</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="Advanced Topics"
|
|
HREF="part5.html"><LINK
|
|
REL="PREVIOUS"
|
|
TITLE="Network Programming"
|
|
HREF="networkprogramming.html"><LINK
|
|
REL="NEXT"
|
|
TITLE="Debugging"
|
|
HREF="debugging.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="networkprogramming.html"
|
|
ACCESSKEY="P"
|
|
>Prev</A
|
|
></TD
|
|
><TD
|
|
WIDTH="80%"
|
|
ALIGN="center"
|
|
VALIGN="bottom"
|
|
></TD
|
|
><TD
|
|
WIDTH="10%"
|
|
ALIGN="right"
|
|
VALIGN="bottom"
|
|
><A
|
|
HREF="debugging.html"
|
|
ACCESSKEY="N"
|
|
>Next</A
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><HR
|
|
ALIGN="LEFT"
|
|
WIDTH="100%"></DIV
|
|
><DIV
|
|
CLASS="CHAPTER"
|
|
><H1
|
|
><A
|
|
NAME="ZEROS"
|
|
></A
|
|
>Chapter 31. Of Zeros and Nulls</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
|
|
>Faultily faultless, icily regular, splendidly null</I
|
|
></P
|
|
><P
|
|
><I
|
|
>Dead perfection; no more.</I
|
|
></P
|
|
><P
|
|
><I
|
|
>--Alfred Lord Tennyson</I
|
|
></P
|
|
></I
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
><A
|
|
NAME="ZEROSREF"
|
|
></A
|
|
></P
|
|
><P
|
|
></P
|
|
><DIV
|
|
CLASS="VARIABLELIST"
|
|
><P
|
|
><B
|
|
><A
|
|
NAME="ZERONULL1"
|
|
></A
|
|
><TT
|
|
CLASS="FILENAME"
|
|
>/dev/zero</TT
|
|
>
|
|
... <TT
|
|
CLASS="FILENAME"
|
|
>/dev/null</TT
|
|
></B
|
|
></P
|
|
><DL
|
|
><DT
|
|
><A
|
|
NAME="DEVNULLREF"
|
|
></A
|
|
>Uses of
|
|
<TT
|
|
CLASS="FILENAME"
|
|
>/dev/null</TT
|
|
></DT
|
|
><DD
|
|
><P
|
|
>Think of <TT
|
|
CLASS="FILENAME"
|
|
>/dev/null</TT
|
|
> as a <I
|
|
CLASS="FIRSTTERM"
|
|
>black
|
|
hole</I
|
|
>. It is essentially the equivalent of
|
|
a write-only file. Everything written to it disappears.
|
|
Attempts to read or output from it result in nothing. All
|
|
the same, <TT
|
|
CLASS="FILENAME"
|
|
>/dev/null</TT
|
|
> can be quite
|
|
useful from both the command-line and in scripts.</P
|
|
><P
|
|
>Suppressing <TT
|
|
CLASS="FILENAME"
|
|
>stdout</TT
|
|
>.
|
|
<TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>cat $filename >/dev/null
|
|
# Contents of the file will not list to stdout.</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
</P
|
|
><P
|
|
>Suppressing <TT
|
|
CLASS="FILENAME"
|
|
>stderr</TT
|
|
>
|
|
(from <A
|
|
HREF="moreadv.html#EX57"
|
|
>Example 16-3</A
|
|
>).
|
|
<TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>rm $badname 2>/dev/null
|
|
# So error messages [stderr] deep-sixed.</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
</P
|
|
><P
|
|
>Suppressing output from <EM
|
|
>both</EM
|
|
>
|
|
<TT
|
|
CLASS="FILENAME"
|
|
>stdout</TT
|
|
> and <TT
|
|
CLASS="FILENAME"
|
|
>stderr</TT
|
|
>.
|
|
<TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>cat $filename 2>/dev/null >/dev/null
|
|
# If "$filename" does not exist, there will be no error message output.
|
|
# If "$filename" does exist, the contents of the file will not list to stdout.
|
|
# Therefore, no output at all will result from the above line of code.
|
|
#
|
|
# This can be useful in situations where the return code from a command
|
|
#+ needs to be tested, but no output is desired.
|
|
#
|
|
# cat $filename &>/dev/null
|
|
# also works, as Baris Cicek points out.</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
</P
|
|
><P
|
|
>Deleting contents of a file, but preserving the file itself, with
|
|
all attendant permissions (from <A
|
|
HREF="sha-bang.html#EX1"
|
|
>Example 2-1</A
|
|
> and <A
|
|
HREF="sha-bang.html#EX2"
|
|
>Example 2-3</A
|
|
>):
|
|
<TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>cat /dev/null > /var/log/messages
|
|
# : > /var/log/messages has same effect, but does not spawn a new process.
|
|
|
|
cat /dev/null > /var/log/wtmp</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
</P
|
|
><P
|
|
>Automatically emptying the contents of a logfile
|
|
(especially good for dealing with those nasty
|
|
<SPAN
|
|
CLASS="QUOTE"
|
|
>"cookies"</SPAN
|
|
> sent by commercial Web sites):</P
|
|
><DIV
|
|
CLASS="EXAMPLE"
|
|
><A
|
|
NAME="COOKIES"
|
|
></A
|
|
><P
|
|
><B
|
|
>Example 31-1. Hiding the cookie jar</B
|
|
></P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
># Obsolete Netscape browser.
|
|
# Same principle applies to newer browsers.
|
|
|
|
if [ -f ~/.netscape/cookies ] # Remove, if exists.
|
|
then
|
|
rm -f ~/.netscape/cookies
|
|
fi
|
|
|
|
ln -s /dev/null ~/.netscape/cookies
|
|
# All cookies now get sent to a black hole, rather than saved to disk.</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
></DD
|
|
><DT
|
|
><A
|
|
NAME="ZEROSREF1"
|
|
></A
|
|
>Uses of <TT
|
|
CLASS="FILENAME"
|
|
>/dev/zero</TT
|
|
></DT
|
|
><DD
|
|
><P
|
|
>Like <TT
|
|
CLASS="FILENAME"
|
|
>/dev/null</TT
|
|
>,
|
|
<TT
|
|
CLASS="FILENAME"
|
|
>/dev/zero</TT
|
|
> is a pseudo-device file, but
|
|
it actually produces a stream of nulls
|
|
(<EM
|
|
>binary</EM
|
|
> zeros, not the <A
|
|
HREF="special-chars.html#ASCIIDEF"
|
|
>ASCII</A
|
|
> kind). Output written
|
|
to <TT
|
|
CLASS="FILENAME"
|
|
>/dev/zero</TT
|
|
> disappears, and it is
|
|
fairly difficult to actually read the nulls emitted there,
|
|
though it can be done with <A
|
|
HREF="extmisc.html#ODREF"
|
|
>od</A
|
|
>
|
|
or a hex editor. <A
|
|
NAME="SWAPFILEREF"
|
|
></A
|
|
>The chief use of
|
|
<TT
|
|
CLASS="FILENAME"
|
|
>/dev/zero</TT
|
|
> is creating an initialized
|
|
dummy file of predetermined length intended as a temporary
|
|
swap file.</P
|
|
><DIV
|
|
CLASS="EXAMPLE"
|
|
><A
|
|
NAME="EX73"
|
|
></A
|
|
><P
|
|
><B
|
|
>Example 31-2. Setting up a swapfile using <TT
|
|
CLASS="FILENAME"
|
|
>/dev/zero</TT
|
|
></B
|
|
></P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>#!/bin/bash
|
|
# Creating a swap file.
|
|
|
|
# A swap file provides a temporary storage cache
|
|
#+ which helps speed up certain filesystem operations.
|
|
|
|
ROOT_UID=0 # Root has $UID 0.
|
|
E_WRONG_USER=85 # Not root?
|
|
|
|
FILE=/swap
|
|
BLOCKSIZE=1024
|
|
MINBLOCKS=40
|
|
SUCCESS=0
|
|
|
|
|
|
# This script must be run as root.
|
|
if [ "$UID" -ne "$ROOT_UID" ]
|
|
then
|
|
echo; echo "You must be root to run this script."; echo
|
|
exit $E_WRONG_USER
|
|
fi
|
|
|
|
|
|
blocks=${1:-$MINBLOCKS} # Set to default of 40 blocks,
|
|
#+ if nothing specified on command-line.
|
|
# This is the equivalent of the command block below.
|
|
# --------------------------------------------------
|
|
# if [ -n "$1" ]
|
|
# then
|
|
# blocks=$1
|
|
# else
|
|
# blocks=$MINBLOCKS
|
|
# fi
|
|
# --------------------------------------------------
|
|
|
|
|
|
if [ "$blocks" -lt $MINBLOCKS ]
|
|
then
|
|
blocks=$MINBLOCKS # Must be at least 40 blocks long.
|
|
fi
|
|
|
|
|
|
######################################################################
|
|
echo "Creating swap file of size $blocks blocks (KB)."
|
|
dd if=/dev/zero of=$FILE bs=$BLOCKSIZE count=$blocks # Zero out file.
|
|
mkswap $FILE $blocks # Designate it a swap file.
|
|
swapon $FILE # Activate swap file.
|
|
retcode=$? # Everything worked?
|
|
# Note that if one or more of these commands fails,
|
|
#+ then it could cause nasty problems.
|
|
######################################################################
|
|
|
|
# Exercise:
|
|
# Rewrite the above block of code so that if it does not execute
|
|
#+ successfully, then:
|
|
# 1) an error message is echoed to stderr,
|
|
# 2) all temporary files are cleaned up, and
|
|
# 3) the script exits in an orderly fashion with an
|
|
#+ appropriate error code.
|
|
|
|
echo "Swap file created and activated."
|
|
|
|
exit $retcode</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
><P
|
|
>Another application of <TT
|
|
CLASS="FILENAME"
|
|
>/dev/zero</TT
|
|
>
|
|
is to <SPAN
|
|
CLASS="QUOTE"
|
|
>"zero out"</SPAN
|
|
> a file of a designated
|
|
size for a special purpose, such as mounting a filesystem
|
|
on a <A
|
|
HREF="devref1.html#LOOPBACKREF"
|
|
>loopback device</A
|
|
>
|
|
(see <A
|
|
HREF="system.html#CREATEFS"
|
|
>Example 17-8</A
|
|
>) or <SPAN
|
|
CLASS="QUOTE"
|
|
>"securely"</SPAN
|
|
>
|
|
deleting a file (see <A
|
|
HREF="extmisc.html#BLOTOUT"
|
|
>Example 16-61</A
|
|
>).</P
|
|
><DIV
|
|
CLASS="EXAMPLE"
|
|
><A
|
|
NAME="RAMDISK"
|
|
></A
|
|
><P
|
|
><B
|
|
>Example 31-3. Creating a ramdisk</B
|
|
></P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>#!/bin/bash
|
|
# ramdisk.sh
|
|
|
|
# A "ramdisk" is a segment of system RAM memory
|
|
#+ which acts as if it were a filesystem.
|
|
# Its advantage is very fast access (read/write time).
|
|
# Disadvantages: volatility, loss of data on reboot or powerdown,
|
|
#+ less RAM available to system.
|
|
#
|
|
# Of what use is a ramdisk?
|
|
# Keeping a large dataset, such as a table or dictionary on ramdisk,
|
|
#+ speeds up data lookup, since memory access is much faster than disk access.
|
|
|
|
|
|
E_NON_ROOT_USER=70 # Must run as root.
|
|
ROOTUSER_NAME=root
|
|
|
|
MOUNTPT=/mnt/ramdisk # Create with mkdir /mnt/ramdisk.
|
|
SIZE=2000 # 2K blocks (change as appropriate)
|
|
BLOCKSIZE=1024 # 1K (1024 byte) block size
|
|
DEVICE=/dev/ram0 # First ram device
|
|
|
|
username=`id -nu`
|
|
if [ "$username" != "$ROOTUSER_NAME" ]
|
|
then
|
|
echo "Must be root to run \"`basename $0`\"."
|
|
exit $E_NON_ROOT_USER
|
|
fi
|
|
|
|
if [ ! -d "$MOUNTPT" ] # Test whether mount point already there,
|
|
then #+ so no error if this script is run
|
|
mkdir $MOUNTPT #+ multiple times.
|
|
fi
|
|
|
|
##############################################################################
|
|
dd if=/dev/zero of=$DEVICE count=$SIZE bs=$BLOCKSIZE # Zero out RAM device.
|
|
# Why is this necessary?
|
|
mke2fs $DEVICE # Create an ext2 filesystem on it.
|
|
mount $DEVICE $MOUNTPT # Mount it.
|
|
chmod 777 $MOUNTPT # Enables ordinary user to access ramdisk.
|
|
# However, must be root to unmount it.
|
|
##############################################################################
|
|
# Need to test whether above commands succeed. Could cause problems otherwise.
|
|
# Exercise: modify this script to make it safer.
|
|
|
|
echo "\"$MOUNTPT\" now available for use."
|
|
# The ramdisk is now accessible for storing files, even by an ordinary user.
|
|
|
|
# Caution, the ramdisk is volatile, and its contents will disappear
|
|
#+ on reboot or power loss.
|
|
# Copy anything you want saved to a regular directory.
|
|
|
|
# After reboot, run this script to again set up ramdisk.
|
|
# Remounting /mnt/ramdisk without the other steps will not work.
|
|
|
|
# Suitably modified, this script can by invoked in /etc/rc.d/rc.local,
|
|
#+ to set up ramdisk automatically at bootup.
|
|
# That may be appropriate on, for example, a database server.
|
|
|
|
exit 0</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
><P
|
|
>In addition to all the above,
|
|
<TT
|
|
CLASS="FILENAME"
|
|
>/dev/zero</TT
|
|
> is needed by ELF
|
|
(<I
|
|
CLASS="FIRSTTERM"
|
|
>Executable and Linking Format</I
|
|
>)
|
|
UNIX/Linux binaries.</P
|
|
></DD
|
|
></DL
|
|
></DIV
|
|
></DIV
|
|
><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="networkprogramming.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="debugging.html"
|
|
ACCESSKEY="N"
|
|
>Next</A
|
|
></TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="left"
|
|
VALIGN="top"
|
|
>Network Programming</TD
|
|
><TD
|
|
WIDTH="34%"
|
|
ALIGN="center"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="part5.html"
|
|
ACCESSKEY="U"
|
|
>Up</A
|
|
></TD
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="right"
|
|
VALIGN="top"
|
|
>Debugging</TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
></BODY
|
|
></HTML
|
|
> |