Rute User's Tutorial and Exposition. 21. System Services and lpd
Next: 22. Trivial Introduction to
Up: rute
Previous: 20. Advanced Shell Scripting
  Contents
Subsections
This chapter covers a wide range of concepts about the way
UNIX services function.
Every function of UNIX is provided by one or another package.
For instance, mail is often handled by the
sendmail or
other package, web by the
apache package.
Here we examine how to obtain, install, and configure
a
package, using
lpd as an example. You can then apply this
knowledge to any other package, and later chapters assume that
you know these concepts. This discussion will also suffice as an
explanation of how to set up and manage printing.
Printing under UNIX on a properly configured machine is as
simple as typing
lpr -Plp <filename> (or
cat
<filename> | lpr -Plp). The ``
lp'' in
-Plp is the
name of the printer queue on the local machine you
would like to print to. You can omit it if you are printing to
the default (i.e., the first listed) queue. A queue
belongs to a physical printer, so users can predict where
paper will come spewing out, by what queue they print to.
Queues are conventionally named
lp,
lp0,
lp1, and so on, and any number of them may have been
redirected to any other queue on any other machine on the
network.
The command
lprm removes pending jobs from
a print queue;
lpq reports jobs in progress.
The service that facilitates all this is called
lpd.
The
lpr user program makes a network connection to the
lpd background process, sending it the print job.
lpd then queues, filters, and feeds the job until it
appears in the print tray.
Printing typifies the client/server nature of UNIX
services. The
lpd background process is the server
and is initiated by the
root user. The remaining commands
are client programs, and are run mostly by users.
The following discussion should relieve the questions of ``Where do I get
xxx service/package?'' and ``How do I install it?''.
Full coverage of package management comes in Section 24.2,
but here you briefly see how to use package managers with respect to a real
system service.
Let us say we know nothing of the service except that it has something
to do with a file
/usr/sbin/lpd. First, we use our package managers
to find where the file comes from (Debian commands are shown in parentheses):
|
rpm -qf /usr/sbin/lpd
( dpkg -S /usr/sbin/lpd )
|
Returns
lpr-0.nn
-n (for RedHat 6.2, or
LPRng-n
.n
.nn
-n on
RedHat 7.0, or
lpr on Debian). On RedHat
you may have to try this on a different machine because
rpm does not know about packages that are not installed.
Alternatively, if we would like to see whether a package
whose name contains the letters
lpr is installed:
|
rpm -qa | grep -i lpr
( dpkg -l '*lpr*' )
|
If the package is not present, the package file will be on your
CD-ROM and is easily installable with (RedHat 7.0 and Debian in braces):
|
rpm -i lpr-0.50-4.i386.rpm
( rpm -i LPRng-3.6.24-2 )
( dpkg -i lpr_0.48-1.deb )
|
(Much more about package management is covered in Chapter 24.)
The list of files which the
lpr package is comprises (easily
obtained with
rpm -ql lpr or
dpkg -L lpr) is approximately as follows:
5
10
|
/etc/init.d/lpd /usr/share/man/man1/lprm.1.gz
/etc/cron.weekly/lpr /usr/share/man/man5/printcap.5.gz
/usr/sbin/lpf /usr/share/man/man8/lpc.8.gz
/usr/sbin/lpc /usr/share/man/man8/lpd.8.gz
/usr/sbin/lpd /usr/share/man/man8/pac.8.gz
/usr/sbin/pac /usr/share/man/man8/lpf.8.gz
/usr/bin/lpq /usr/share/doc/lpr/README.Debian
/usr/bin/lpr /usr/share/doc/lpr/copyright
/usr/bin/lprm /usr/share/doc/lpr/examples/printcap
/usr/bin/lptest /usr/share/doc/lpr/changelog.gz
/usr/share/man/man1/lpr.1.gz /usr/share/doc/lpr/changelog.Debian.gz
/usr/share/man/man1/lptest.1.gz /var/spool/lpd/lp
/usr/share/man/man1/lpq.1.gz /var/spool/lpd/remote
|
(The word legacy with regard to software means
outdated, superseded, obsolete, or just old.)
RedHat 7.0 has now switched to using
LPRng rather than the legacy
lpr that Debian and other distributions use.
LPRng is a
more modern and comprehensive package. It supports the same
/etc/printcap
file and identical binaries as did the legacy
lpr on RedHat 6.2.
The only differences are in the control files created in your spool
directories, and a different access control mechanism (discussed below).
Note that
LPRng has strict permissions requirements on spool
directories and is not trivial to install from source.
A package's many files can be loosely grouped into functional elements.
In this sectiom, each element will be explained, drawing on the
lpr
package as an example. Refer to the list of files in Section
21.2.
Documentation should be your
first and foremost interest. Man
pages will not always be the only documentation provided.
Above we see that
lpr does not install very much
into the
/usr/share/doc directory. However, other
packages, like
rpm -ql apache, reveal a huge user manual (in
/home/httpd/html/manual/ or
/var/www/html/manual/), and
rpm -ql wu-ftpd
shows lots inside
/usr/doc/wu-ftpd-?
.?
.?.
Every package will probably have a team that maintains it as
well as a web page. In the case of
lpd, however, the
code is very old, and the various CD vendors do maintenance on
it themselves. A better example is the
lprNG package.
Go to The LPRng Web Page <http://www.astart.com/lprng/LPRng.html>
with your web browser. There you can see the authors,
mailing lists, and points of download.
If a particular package is of much
interest to you, then you should become familiar with these
resources. Good web pages will also have additional
documentation like troubleshooting guides and FAQs
(Frequently Asked Questions). Some may even have archives
of their mailing lists. Note that some web pages are geared
more toward CD vendors who are trying to create their own
distribution and so will not have packages for download that
beginner users can easily install.
User programs are found in one or another
bin directory. In this case,
we can see
lpq,
lpr,
lprm, and
lptest,
as well as their associated
man pages.
Daemon and administrator command will an
sbin directory. In this case
we can see
lpc,
lpd,
lpf, and
pac, as
well as their associated
man pages. The only
daemon (background) program is really the
lpd
program itself, which is the core of the whole package.
The file
/etc/printcap controls
lpd. Most system
services will have a file in
/etc.
printcap is a plain
text file that
lpd reads on startup. Configuring any
service primarily involves editing its configuration file. Several
graphical configuration tools are available that avoid this
inconvenience (
printtool, which is especially for
lpd,
and
linuxconf), but these actually just silently produce the
same configuration file.
Because printing is so integral to the system,
printcap is not
actually provided by the
lpr package. Trying
rpm -qf /etc/printcap gives
setup-2.3.4-1, and
dpkg -S /etc/printcap shows it to not be owned (i.e., it is part of
the base system).
The files in
/etc/rc.d/init.d/ (or
/etc/init.d/) are the
startup and shutdown scripts to run
lpd on boot and shutdown. You
can start
lpd yourself on the command-line with
but it is preferably to use the given script:
|
/etc/rc.d/init.d/lpd start
/etc/rc.d/init.d/lpd stop
|
(or
/etc/init.d/lpd). The script has other uses as well:
|
/etc/rc.d/init.d/lpd status
/etc/rc.d/init.d/lpd restart
|
(or
/etc/init.d/lpd).
To make sure that
lpd runs on startup, you
can check that it has a symlink under the appropriate run level.
The symlinks can be explained by running
|
ls -al `find /etc -name '*lpd*'`
find /etc -name '*lpd*' -ls
|
showing,
5
10
|
-rw-r--r-- 1 root root 17335 Sep 25 2000 /etc/lpd.conf
-rw-r--r-- 1 root root 10620 Sep 25 2000 /etc/lpd.perms
-rwxr-xr-x 1 root root 2277 Sep 25 2000 /etc/rc.d/init.d/lpd
lrwxrwxrwx 1 root root 13 Mar 21 14:03 /etc/rc.d/rc0.d/K60lpd -> ../init.d/lpd
lrwxrwxrwx 1 root root 13 Mar 21 14:03 /etc/rc.d/rc1.d/K60lpd -> ../init.d/lpd
lrwxrwxrwx 1 root root 13 Mar 21 14:03 /etc/rc.d/rc2.d/S60lpd -> ../init.d/lpd
lrwxrwxrwx 1 root root 13 Mar 24 01:13 /etc/rc.d/rc3.d/S60lpd -> ../init.d/lpd
lrwxrwxrwx 1 root root 13 Mar 21 14:03 /etc/rc.d/rc4.d/S60lpd -> ../init.d/lpd
lrwxrwxrwx 1 root root 13 Mar 28 23:13 /etc/rc.d/rc5.d/S60lpd -> ../init.d/lpd
lrwxrwxrwx 1 root root 13 Mar 21 14:03 /etc/rc.d/rc6.d/K60lpd -> ../init.d/lpd
|
The ``
3'' in
rc3.d is the what are interested in.
Having
S60lpd symlinked to
lpd under
rc3.d
means that
lpd will be started when the system enters
run level 3, which is the system's state of usual operation.
Note that under RedHat the command
setup has a menu option
System Services. The
Services list will allow you to
manage what services come alive on boot, thus creating the symlinks
automatically. For Debian, check the man page for the
update-rc.d command.
More details on bootup are in Chapter 32.
Systems services like
lpd,
innd,
sendmail,
and
uucp create intermediate files in the course of
processing each request. These are called spool files
and are stored somewhere under the
/var/spool/ directory,
usually to be processed and then deleted in sequence.
lpd has a spool directory
/var/spool/lpd,
which may have been created on installation. You can create
spool directories for the two printers
in the example below, with
|
mkdir -p /var/spool/lpd/lp /var/spool/lpd/lp0
|
UNIX has a strict policy of not reporting error messages to the user
interface whenever there might be no user around to read those messages.
Whereas error messages of interactive commands are sent to the terminal
screen, error or information messages produced by non-interactive
commands are ``logged'' to files in the directory
/var/log/.
A log file is a plain text file that continually has one-liner status
messages appended to it by a daemon process. The usual
directory for log files is
/var/log. The main log files are
/var/log/messages and possibly
/var/log/syslog.
It contains kernel messages and
messages from a few primary services. When a service would
produce large log files (think web access with thousands of hits
per hour), the service would use its own log file.
sendmail,
for example, uses
/var/log/maillog. Actually,
lpd
does not have a log file of its own--one of its failings.
View the system log file with the
follow option
to
tail:
|
tail -f /var/log/messages
tail -f /var/log/syslog
|
Restarting the
lpd service gives messages
like: [Not all distributions log this information.]
|
Jun 27 16:06:43 cericon lpd: lpd shutdown succeeded
Jun 27 16:06:45 cericon lpd: lpd startup succeeded
|
Log files are rotated daily or weekly by the
logrotate package.
Its configuration file is
/etc/logrotate.conf. For each package
that happens to produce a log file, there is an additional configuration
file under
/etc/logrotate.d/. It is also easy to write your own--begin
by using one of the existing files as an example. Rotation means that the log
file is renamed with a
.1 extension and then truncated to zero
length. The service is notified by the
logrotate program, sometimes
with a
SIGHUP. Your
/var/log/ may contain a number of old
log files named
.2,
.3, etc. The point of log file rotation
is to prevent log files from growing indefinitely.
Most user commands of services make use of some environment variables.
These can be defined in your shell startup scripts as usual. For
lpr, if no printer is specified on the command-line, the
PRINTER environment variable determines the default print
queue. For example,
export PRINTER=lp1 will force use of the
lp1 print queue.
The
printcap
(printer capabilities) file is similar to (and
based on) the
termcap
(terminal capabilities) file.
Configuring a printer means adding or removing text in this
file.
printcap contains a list of one-line entries, one for each printer.
Lines can be broken by a
\ before the newline. Here is an
example of a
printcap file for two printers.
5
10
|
lp:\
:sd=/var/spool/lpd/lp:\
:mx#0:\
:sh:\
:lp=/dev/lp0:\
:if=/var/spool/lpd/lp/filter:
lp0:\
:sd=/var/spool/lpd/lp0:\
:mx#0:\
:sh:\
:rm=edison:\
:rp=lp3:\
:if=/bin/cat:
|
Printers are named by the first field: in this case
lp is the first printer and
lp0 the
second printer. Each printer usually refers to a different
physical device with its own queue. The
lp printer should
always be listed first and is the default print queue used when
no other is specified. Here,
lp refers to a local printer on
the device
/dev/lp0 (first parallel port).
lp0 refers
to a remote print queue
lp3 on the machine
edison.
The
printcap has a comprehensive
man page.
However, the following fields are most of what you will ever need:
-
sd
- Spool directory. This directory contains status and spool files.
-
mx
- Maximum file size. In the preceding example, unlimited.
-
sh
- Suppress headers. The header is a few informational lines printed
before or after the print job. This option should always be set to off.
-
lp
- Line printer device.
-
if
- Input filter. This is an executable script into which printer
data is piped. The output of this script is fed directly to the
printing device or remote machine. This filter will translate
from the application's output into the printer's
native code.
-
rm
- Remote machine. If the printer queue is not local, this is the
machine name.
-
rp
- Remote printer queue name. The remote machine will have its
own
printcap file with possibly several printers defined.
This specifies which printer to use.
On UNIX the standard format for all printing is the PostScript
file. PostScript
.ps files are graphics files representing
arbitrary scalable text, lines, and images. PostScript is actually
a programming language specifically designed to draw things on
a page; hence,
.ps files are really PostScript programs.
The last line in any PostScript program is always
showpage,
meaning that all drawing operations are complete and that the page
can be displayed. Hence, it is easy to see the number of pages
inside a PostScript file by
grepping for the string
showpage.
The procedure for printing on UNIX is to convert whatever you
would like to print into PostScript. PostScript files can be
viewed with a PostScript ``emulator,'' like the
gv
(GhostView) program. A program called
gs (GhostScript)
is the standard utility for converting the PostScript into a
format suitable for your printer. The idea behind PostScript is
that it is a language that can easily be built into any printer. The
so-called ``PostScript printer'' is one that directly interprets a
PostScript file. However, these printers are relatively
expensive, and most printers only understand the lesser PCL
(printer control language) dialect or some other format.
In short, any of the hundreds of different formats of graphics
and text have a utility that will convert a file into PostScript,
whereafter
gs will convert it for any of the hundreds of
different kinds of printers. [There are actually many
printers not supported by
gs at the time of this writing.
This is mainly because manufacturers refuse to release
specifications to their proprietary
printer communication protocols]. The print filter
is the workhorse of this whole operation.
Most applications conveniently output PostScript whenever
printing. For example,
netscape's
menu selection shows
which sends PostScript through the stdin of
lpr.
All applications without their own printer drivers will do the
same. This means that we can generally rely on the fact that
the print filter will always receive PostScript.
gs, on the
other hand, can convert PostScript for any printer, so all that
remains is to determine its command-line options.
If you have chosen ``Print To: File,'' then you can view the resulting output
with the
gv program. Try
gv netscape.ps, which
shows a print preview. On UNIX,
most desktop applications do not have their own preview facility
because the PostScript printer itself is emulated by
gv.
Note that filter programs should not be used with remote filters;
remote printer queues can send their PostScript files ``as is'' with
:if=/bin/cat: (as in the example
printcap file
above). This way, the machine connected to the device need be
the only one especially configured for it.
The filter program we are going to use for the local
print queue will be a shell script
/var/spool/lpd/lp/filter.
Create the filter with
|
touch /var/spool/lpd/lp/filter
chmod a+x /var/spool/lpd/lp/filter
|
then edit it so that it looks like
|
#!/bin/bash
cat | gs -sDEVICE=ljet4 -sOutputFile=- -sPAPERSIZE=a4 -r600x600 -q -
exit 0
|
The
-sDEVICE option describes the printer, in
this example a Hewlett Packard LaserJet 1100. Many printers
have similar or compatible formats; hence, there are far
fewer
DEVICE's than different makes of printers. To get
a full list of supported devices, use
gs -h and also
consult one of the following files (depending on your distribution):
/usr/doc/ghostscript-?
.??
/devices.txt
/usr/share/doc/ghostscript-?
.??
/Devices.htm
/usr/share/doc/gs/devices.txt.gz
The
-sOutputFile=- sets to write to stdout (as required
for a filter). The
-sPAPERSIZE
can be set to one of
11x17,
a3,
a4,
a5,
b3,
b4,
b5,
halfletter,
ledger,
legal,
letter,
note, and others listed in
the
man page. You can also use
-g<width>x<height> to set the exact page size in pixels.
-r600x600 sets the resolution, in this case, 600 dpi
(dots per inch).
-q means to set quiet mode, suppressing any
informational messages that would otherwise corrupt the
PostScript output, and
- means to read from
stdin and not from a file.
Our printer configuration is now complete. What remains
is to start
lpd and test print. You can do that on the
command-line with the
enscript package.
enscript
is a program to convert plain text files into nicely formatted
PostScript pages. The
man page for
enscript shows
an enormous number of options, but we can simply try:
|
echo hello | enscript -p - | lpr
|
You should be very careful about running
lpd
on any machine that is exposed to the Internet.
lpd has
had numerous security alerts [See Chapter 44.]and should really only be used within a trusted LAN.
To prevent any remote machine from using your printer,
lpd
first looks in the file
/etc/hosts.equiv. This is a simple
list of all machines allowed to print to your printers. My own file
looks like this:
|
192.168.3.8
192.168.3.9
192.168.3.10
192.168.3.11
|
The file
/etc/hosts.lpd does the same but doesn't give
administrative control by those machines to the print queues. Note that
other services, like
sshd and
rshd
(or
in.rshd), also
check the
hosts.equiv file and consider any machine listed to be
equivalent. This means that they are completed trusted
and so
rshd will not request user logins between machines to be
authenticated. This behavior is hence a grave security concern.
LPRng on RedHat 7.0 has a different access control
facility. It can arbitrarily limit access in a variety of ways,
depending on the remote user and the action (such as who is allowed to
manipulate queues). The file
/etc/lpd.perms
contains the configuration. The file format is simple, although
LPRng's capabilities are rather involved--to make a long
story short, the equivalent
hosts.equiv becomes in
lpd.perms
5
|
ACCEPT SERVICE=* REMOTEIP=192.168.3.8
ACCEPT SERVICE=* REMOTEIP=192.168.3.9
ACCEPT SERVICE=* REMOTEIP=192.168.3.10
ACCEPT SERVICE=* REMOTEIP=192.168.3.11
DEFAULT REJECT
|
Large organizations with many untrusted users
should look more closely at the
LPRng-HOWTO in
/usr/share/doc/LPRng-n
.n
.nn.
It explains how to limit access in more complicated ways.
Here is a convenient order for checking what is not working.
- 1.
- Check that your printer is plugged in and working.
All printers have a way of printing a test page. Read your printer
manual to find out how.
- 2.
- Check your printer cable.
- 3.
- Check your CMOS settings for your parallel port.
- 4.
- Check your printer cable.
- 5.
- Try
echo hello > /dev/lp0 to check that the port
is operating. The printer should do something to signify
that data has at least been received. Chapter 42
explains how to install your parallel port kernel module.
- 6.
- Use the
lpc program to query the
lpd
daemon. Try
help, then
status lp, and so on.
- 7.
- Check that there is enough space in your
/var
and
/tmp devices for any intermediate files needed
by the print filter. A large print job may require
hundreds of megabytes.
lpd may not give any kind
of error for a print filter failure: the print job may
just disappear into nowhere. If you are using legacy
lpr,
then complain to your distribution vendor about your print filter
not properly logging to a file.
- 8.
- For legacy
lpr, stop
lpd and
remove all of
lpd's runtime [At or pertaining to the program being in a running state.] files from
/var/spool/lpd
and from any of its subdirectories. (New
LPRng should never
require this step.) The unwanted files are
.seq,
lock,
status,
lpd.lock, and any left
over spool files that failed to disappear with
lprm (these
files are recognizable by long file names with a host name
and random key embedded in the file name). Then, restart
lpd.
- 9.
- For remote queues, check that you can do forward and
reverse lookups on both machines of both machine's
host names and IP address. If not, you may get
Host name for your address (ipaddr
) unknown error
messages when trying an
lpq.
Test with the command
host <ip-address>
and also
host <machine-name> on both machines. If any
of these do not work, add entries for both machines in
/etc/hosts from the example on page
. Note that the
host command may
be ignorant of the file
/etc/hosts and may still fail.
Chapter 40 will explain name lookup configuration.
- 10.
- Run your print filter manually to check that it does,
in fact, produce the correct output. For example,
echo hello | enscript -p - | /var/spool/lpd/lp/filter > /dev/lp0.
- 11.
- Legacy
lpd is a bit of a quirky package--meditate.
printtool is a graphical printer setup program that helps
you very quickly set up
lpd. It immediately
generates a
printcap file and magic filter, and
you need not know anything about
lpd configuration.
apsfilter stands for any to PostScript filter.
The setup described above requires everything be converted to
PostScript before printing, but a filter could foreseeably use the
file command to determine the type of data coming in
and then invoke a program to convert it to PostScript before
piping it through
gs. This would enable JPEG, GIF, plain text,
DVI files, or even
gzipped HTML to be printed
directly, since PostScript converters have been written for
each of these.
apsfilter is one of a few such filters, which are
generally called magic filters. [This is because the
file command uses magic numbers. See page .]
I personally find this feature a gimmick rather than a genuine
utility, since most of the time you want to lay out the graphical
object on a page before printing, which requires you to preview it,
and hence convert it to PostScript manually. For most
situations, the straight PostScript filter above will work
adequately, provided users know to use
enscript instead
of
lpr when printing plain text.
mpage is a useful utility for saving the trees.
It resizes PostScript input so that two, four or eight
pages fit on one. Change your print filter to:
|
#!/bin/bash
cat | mpage -4 | gs -sDEVICE=ljet4 -sOutputFile=- -sPAPERSIZE=a4 -r600x600 -q -
exit 0
|
The package
psutils contains a variety of
command-line PostScript manipulation programs--a must for anyone
doing fancy things with filters.
The
printcap allows anything to be specified as the
printer device. If we set it to
/dev/null and let our filter
force the output to an alternative device, then we can use
lpd
to redirect ``print'' jobs to any kind of service imaginable.
Here,
my_filter.sh is a script that might send the print
job through an SMB (Windows NT) print
share (using
smbclient--see
Chapter 39), to a printer previewer, or
to a script that emails the job somewhere.
5
|
lp1:\
:sd=/var/spool/lpd/lp1:\
:mx#0:\
:sh:\
:lp=/dev/null:\
:if=/usr/local/bin/my_filter.sh:
|
We see a specific example of redirecting print jobs
to a fax machine in Chapter 33.
Next: 22. Trivial Introduction to
Up: rute
Previous: 20. Advanced Shell Scripting
  Contents
|