Printing Clients and Servers

Last time, we configured two commodity home printers to work with a FreeBSD system. Now we'll learn how to use FreeBSD's built-in tools to configure this system as a print server for other UNIX boxes and how to configure client machines to use this server.
While there are many add-on programs that claim to make client printing easier,
I find lpd(8) and its friends very quick and easy.

The Server

Start by making the printer work on the system you want to be the server.
While the lpd(8) daemon that gets print jobs to the printer
listens to the network by default, it doesn't accept print requests from just
anyone. You must list the hostnames or IP addresses of permitted clients in
/etc/hosts.lpd, each on a single line. I recommend using IP
addresses so that a DNS failure won't take printing with it.

The Client

Printer client configuration is identical for any server that runs
lpd(8). This means that your FreeBSD client can use any print
server from the integrated lpd(8), add-on programs such as LPRng,
or even Microsoft's Print Services for UNIX, without changing your client
configuration. Here's a typical /etc/printcap configuration for a
printing client.

Just like termcap(5), each printer entry is technically a
single line. The backslash character indicates that an entry continues on the
next line. Also, each configuration option begins and ends with colons.

The first line is the printer name. This client has two names for this
printer, lp and networkdept. lp is the
standard UNIX name for the default printer, but I added
networkdept as a friendly reminder. A printer can have any number
of names — separate them with the pipe character, as shown above.

The second line, lp, lists the device name for this printer.
As we're configuring a client for a network printer, leave the device name
empty.

The third line, rp, gives the name that the print server uses
for the printer in question. The print server's /etc/printcap
lists the printer outside my office as networkdept, so that's the
printer name I use.

The rm entry gives the hostname of the print server, in this
case print. If your print server is in a different domain, use a
fully qualified domain name here.

The fourth line, sd, lists the spool directory used for this
printer. Every printer in your /etc/printcap needs a unique spool
directory, which you must create before trying to use the printer.

Finally, the lf entry gives the full path to the log file.
Unlike the spool directory, printers can share a log file.

Once you have configured a printer, fire up the printer daemon on your
client. It doesn't matter if your printer is attached to the local machine or
elsewhere on the network, the system still needs a daemon to send print jobs to
the printer. You can now hit Print in your application and it should "just
work."

Configuring Multiple Print Servers

So far, so easy? Now let's get slightly more complicated. This particular
client machine is my laptop. I have one print server at work and another at
home. The configuration above is for the work printer, but I want to come home
and have everything magically work. I don't mind choosing a different printer
in the OpenOffice Print dialog, but I don't want to change anything in
/etc. Here's my laptop's configuration for my home laser printer.
(We configured this printer in my last article.)

The configuration looks quite similar, but with a few vital changes. The
printer is named lp2 or homelaser. lp2
is the old-fashioned UNIX name for the second laser printer on the system. The
print server knows this printer as lp, so that's the remote
printer name. My home print server is called
sardines.blackhelicopters.org. (I use the full domain name
because the laptop has a hostname under the office's corporate domain.)
By making this entry in /etc/printcap, I can access either printer.
Of course, I must restart lpd(8) after making the edit, which will
interrupt existing printing jobs. If this is a problem, as it might be on a
high-volume print server, check out lpc(8) to make lpd reread its
configuration file, restart individual printers, and perform other maintenance
tasks. For a print client, lpc(8) is usually overkill.

Print Job Management

One common question printer clients have is, "Where is my print job?" The
easiest way to tell is to check the print queue with lpq(1). Use
the -P flag to identify a printer. For example, if I want to know
if my last print job went to my home printer, I can run:

# lpq -P homelaser
no entries
#

The print server has no entries in its queue for this printer. My print job
has probably gone on to the printer. Of course, the printer could have be
chewing up the paper or spitting out reams of garbage, but that's a different
problem. If the print server were still chewing on my print job, the entry
would look a little more like this.

If the print job were still sitting there after a while, I'd have to go log
into the print server and look at the error log to see what was happening.

Many graphical programs, such as Mozilla, have a field where you can set a
flag to choose a printer. Desktop environments such as KDE and Gnome have
places where you can set printers and flags in a nice menu-driven format.
Applications such as OpenOffice have a special tool used to configure
application printers.

My only real problem with a multi-environment printing setup is that I
continually send print jobs to the wrong printer. This isn't just a matter of
"Oh, I have to walk across the office to the other printer" -- the printer I sent
the job to doesn't even exist in the environment I'm in! If you're wondering
where your print job went, check the queue for the other environment. For
example, if I'm working at home on the weekend and just hit the Print button,
the print job will go to the laptop's default (i.e., workplace)
queue and hang there.

The second line, with the "no daemon present" warning, indicates that
something's wrong with the printer. The easy guess is that I can't talk to
that printer from the wrong side of the corporate firewall. If I leave those
print jobs in the queue, when I go into work and plug in, the printer outside of my
office will start to spew everything I wanted to print over the weekend. This
may include things that I don't want to leave sitting on the work printer, so
it's a good idea to clean out that queue.

lprm(1) removes jobs from the printer queue. lprm
takes a whole variety of arguments, but the most useful for this purpose is a
simple dash (-). This tells lpd(8) to remove all
print jobs that belong to the user who is running the program. You can choose
a printer with the -P flag, exactly as you can when viewing the print
queue.

You can also use this to cancel print jobs if you hit print by mistake, but
modern print servers work very quickly. By the time you type lprm
-, the print server will have almost certainly already sent the job to
the printer, and it will be far too late to cancel the job.

Further Reading

If you're really interested in printing, be sure to check the manual pages
for lpd(8), lpr(1), and printcap(5).
However, what we've covered here should be enough to have a basic setup working in only
a few minutes. Happy printing!