Linux Printing Systems
Kwan L. Lowe
Date: 15 November 2002
Printing, unfortunately can sometimes seem a lot more
difficult that it really is. In this talk I'll try to cover what happens
when you send a file off to be printed, whether through an application
print menu or by calling the print spooler directly. In addition to the
traditional unix lpr printing system, I'll also cover CUPS (the Common
Unix Printing System) and LPRng (LPR, the Next Generation) and printing
through non-Unix print resources such as the Windows printing facility.
The current version of this document is available at the author's website at:
http://www.digitalhermit.com/linux/printing/index.html
Anyone remember dot matrix printers? At that time, printing was as easy as
copying a file to the print device. Though computers have gotten a lot more
sophisticated since then, sometimes it appears that the printing process has
become much more convoluted and difficult. Why add the relative complexity of
a printing system when the old way seemed so much easier?
The printing system does several things:
- Abstracts the printer specific control commands from applications
- Allows multiple users and process access to the print device
- Provides a system of job control and queue management
- Provides an authentication/authorization layer
In the simplest case with a directly connected ASCII capable line printer,
you can merely cat text files to the appropriate device and watch it
print.
1
For example:
[klowe@omega] cat outfile.txt > /dev/lp0
This works fine if you're printing pure text to a locally attached device
that supports it. Modern printers do a lot more, however, and to exploit
their features such as graphics, Postscript, HP PCL (Printer Control
Language) we need to filter the input to the printer. Of course, not
all printers are Postscript or PCL compatible so the print system serves
the purpose of translating the input into a format that is understood
by the printer. This allows applications to be relatively ignorant of
the capabilities and driver requirements of the printer, but still take
full advantage of them. On another level, the printing system allows a
client to submit jobs to printers across a network or even across the Internet.
The actual print device in the
dev filesystem, like other
devices, can only be used by a single process at a time. Linux gets
around this by having one process take ownership of the device and then
acting as an arbitrator to the resource. In the case of printing, the lpd
process takes control of the print device and listens for connections
from clients, either local or remote, and processes their submitted jobs.
The next big reason for using the print system is related to the
first. Printing is a slow process and takes eons in comparison to
some of the other things going on in the system. The print server does
an important function in
queueing items for printing. In most
cases the server operates on a first-come, first served basis, spooling
the jobs to the print device in the order in which they appear but it can
also re-order the jobs to be printed, remove jobs from the print queue,
reprint jobs, or schedule the job for later printing.
Finally, the printing system limits the print resources to only authorized
clients. It can limit when and how often users can submit jobs to the queue. It
can limit the size or usage of printers.
We've already seen the trivial example of sending a file directly to a
print device. What happens when a print system in used instead?
The first step in the chain is the submitting of the file to the print
queue via the lpr utility (or whatever the print front-end is for the
printing system). Using a utility known as a magic filter
2, lpr determines the input file type and prepares the document
for sending to the print device. This requires some knowledge of both
the input format and the printer capabilities. For example, if a user
sends a pure ASCII text document for printing to a remote Postscript
printer, the print system will first convert the text to Postscript using
Ghostscript 3then send it across the network to the remote printer. Once
the file is in a format compatible with the print device, it is placed
in a queue to await its turn.
In this section we'll take a look at some of the various print systems
available for Linux. Though they differ in their functionality, scope, and
administration procedures, they do maintain at least some compatibility
with traditional commands.
lpr and
lp refer to the traditional Unix print
systems. After the Great Schism hinted at by gray bearded Unix old-timers,
there were two main print systems, the BSD style and the SysV style. They
were, from and end-user standpoint, rather comparable in their abilities
but differed in implementation details.
BSD is considered by some to be more network friendly and better able
to scale to large workgroups. BSD systems use lpr to submit
jobs to the queue. lpq to show the contents of the queue, and
lprm to remove jobs from the queue. SysV UNIX uses lp to submit, lpstat to show queue contents, and cancel to remove jobs.
In general, Linux has tended towards the BSD print system in earlier
distributions. In more recent offerings from RedHat, SuSe, and Mandrake
the print systems install compatibility layers that mimic both BSD and
SysV commands. The example in the previous section used commands from
the BSD system though the print system is actually LPRng, which we'll
discuss next.
For an example of LPR/LP administration We'll send a file to be printed to a dummy
printer and show what happens to the file as it passes through the
system. The first thing we'll do is to create a dummy printer using the
old-fashioned tool of a text editor. This dummy printer will do nothing
to the input file except echo it verbatim to a temporary file.
First, edit the
/etc/printcap file to add the
dummy device. printcap is the ``print capabilities'' database.
4
1 dummy:\
2 :sd=/var/spool/lpd/dummy:\
3 :sh:\
4 :lp=|/usr/share/printconf/util/nofilter:
We'll use this opportunity to explain some basic options of the printcap file. dummy of course refers to the queue name. sd specifies
the spool directory where jobs are held as they await printing. sh instructs the print system to suppress headers and banner pages. lp specifies the device name or file to which the output is sent. For a full
explanation of all the printcap options, please refer to the printcap manual pages.
Next, we create a null print filter that just echoes whatever it receives on
stdin straight back to a temporary file. In this case, we edit the
./nofilter file.
#!/bin/sh
exec 1>"/tmp/outfile"
/bin/cat
Once the dummy filter is created, we restart the lpd server. For
example:
[root@omega]# /sbin/service lpd restart
Stopping lpd: [ OK ]
Starting lpd: [ OK ]
The new print queue has been added and is now ready for testing. We'll pipe
some text directly to
lpr by typing:
[root@omega]# fortune | lpr -P dummy
If everything worked correctly we should be able to look in /tmp/outfile for our text. Sure enough, a peek inside of /tmp/outfile shows the
output from our fortune program:
[root@omega] cat /tmp/outfile
The camel died quite suddenly on the second day, and Selena
fretted sullenly and, buffing her already impeccable nails --
not for the first time since the journey begain -- pondered
snidely if this would dissolve into a vignette of minor
inconveniences like all the other holidays spent with Basil.
-- Winning sentence, 1983 Bulwer-Lytton bad fiction contest.
One is not limited to pure text printing, of course. Part of the print system
is a series of filters that not only do the work of converting from
one format to another, but also change the appearance of documents.
There are a host of other input filters availabe. Some do nothing
more than strip carriage returns and line feeds from the input
text. Others will detect C source code and apply line-numbering and
syntax highlighting. There are even filters to automatically arrange
pages for making folded pamphets and to print multiple pages per sheet.
Though this was a trivial example, it does serve to show how the print
system filters input before sending it to the print device. In a normal
print queue, the print system will use a magic filter to first
determine the input type. Without the magic filter, sending a Postscript
file to a Postscript printer may result in the raw source code being
printed. Unless one happens to be troubleshooting Postscript itself,
this result is unlikely to be desirable.
LPRng (LPR Next Generation) provides huge improvements over the
traditional print systems. It integrates well into heterogenous networks
and is being actively developed. As mentioned, LPRng provides emulation
of traditional printing commands so many scripts and utilities will work
as expected. The homepage at
http://www.lprng.com/ describes
some of its advantages and features:
The LPRng print spooler is an enhanced, extended, and portable
implementation of the Berkeley lpr print spooler functionality. While
providing the same interface and meeting RFC1179 requirements, the
implementation is completely independent and provides support for the
following features: lightweight (no databases needed) lpr, lpc, and
lprm programs; dynamic redirection of print queues; printer pooling
and load balancing; automatic job holding; highly verbose diagnostics;
client programs do not need to run SETUID root; greatly enhanced security
checks; load balancing across multiple printers; and a greatly improved
permission and authorization mechanism.
TOBEWRITTEN
CUPS, the Common UNIX Printing System, is an ambitious project
to provide a common printing environment across different Unix and
Unix-like implementations, including Linux. Some of its main features
include the ability discover print resources, provide a web-based
administration front-end, and support a wide variety of existing and
new print systems. From the overview page at
http://www.cups.org :
CUPS uses IPP/1.1 5 to provide a complete,
modern printing system for UNIX that can be extended to support new
printers, devices, and protocols while providing compatibility with
existing UNIX applications.
Figure
1 shows the main CUPS administration screen.
One useful feature of the CUPS administration page is that it is accessible
via any standard HTML browser. Though its configuration files can be
edited directly, the browser front end can do all the main administration
tasks. To access the administration screen, point your browser to
x.x.x.x:631 , where x.x.x.x is the IP address of the machine on
which the CUPS server is running.
6
Figure 1:
Main CUPS Screen
|
Clicking on the Do Administration Tasks link (Figure 2)
will load the module that will allow the addition and deletion of printers,
definition of classes, and queue/job management.
Figure 2:
CUPS Administration Screen
|
From the Admin page, click on the Add Printer link to
define a printer on the system. A screen similar to Figure 3
will appear. Enter the name, location, and description of the printer.
Figure 3:
CUPS Add Printer
|
Next, select the type of printing device from the drop-down menu.
As of this writing, CUPS supports the following printing protocols:
- AppSocket/Hp JetDirect
- Internet Printing Protocol (http)
- Internet Printing Protocol (ipp)
- LPD/LPR Host or Printer
- Windows Printer via Samba
The AppSocket/HPJetDirect option is used for many types of network-aware
printers. The JetDirect devices, of which compatible devices are sold by
different companies, is essentially a remote parallel port. JetDirect devices
listen on TCP port 9100, and printing to them is a matter of sending the
raw print commands directly to this port. The JetDirects can often support
multiple parallel ports and can help eliminate some of the interrupt conflicts
when dealing with legacy x86 equipment.
The Internet Printing Protocol, as mentioned previously,
is a proposed standard for printing systems that will allow, among
other things, the ability to print across the Internet. Besides making
facsimile devices somewhat obsolete, it could allow easier and better
printing networks. The downside is that it is a relatively new standard
7 and not widely supported.
LPD/LPR were discussed previously where we mentioned that
the LPR system is a client/server model. As in most Linux servers, the
clients need not be on the same physical machine and can be configured
to listen for remote TCP connections. One main downside is the relatively
poor authentication mechanisms available for this system.
Finally, shared Windows printers are also supported via the Samba
8 suite. Though Windows
has gained a reputation for its inability to work with non-Windows applications,
instability, bloat, anti-trust violations and general evil, it is somewhat
ubiquitous in many corporate offices. In fact, there are some non-PC network
printer devices (similar to the JetDirects) and even some printers, that
advertise themselves on the network as a Windows printer.
For our example we'll choose an HP JetDirect printer. Like CUPS, the JetDirects
can be administered via a browser. One can also telnet directly into
the JetDirect to change passwords, IP information, and other features. Refer
to the user manuals for more information.
Next, we are prompted for the Device URI. Becase we are printing to a socket
on a remote device, we specify the URI as socket://192.168.1.100:9100.
Of course, substitute the correct IP information for your device. If the
JetDirect supports multiple printers they are often accessed by incrementing
the port number. Thus, for the second printer on a single JetDirect device
we'd use socket://192.168.1.100:9101.
Then, select the Model/Driver for the new device on next two screens. The list
of supported printers is quite extensive. If however, you do not find your
identical model, try one that seems close. On a related note, use the correct
model if you do find it on the list. Though Postscript itself should create
pages identically on different printers, there may be slight differences in
margins and color/grayscale manipulation that can affect print quality.
9
Like LPRng, CUPS emulates the traditional print administration commands.
Either
cancel or
lprm can be used to dequeue, or remove,
jobs from the spooler.
lpstat shows the printer status:
[klowe@omicron klowe]$ lpstat -p
printer print@omicron unknown state. enabled since Nov 13 21:33 2002. available
Printer: print@omicron
Queue: no printable jobs in queue
Server: no server active
Status: job 'klowe@omicron+62' removed at 16:00:11.980
Rank Owner/ID Class Job Files Size Time
done klowe@omicron+11 A 11 printing.ps 60249 20:16:38
Another useful feature of CUPS is its ability to create
print pools which
allow jobs to be submitted to a collection of printers and print on the first
available one. To define this collection, called a
class in the CUPS
system, choose the
Add Classoption from the Administration menu. Define a
name, location, and description for the print class. Next, select the list of
printers that belong to the class. When this is completed, the class can be
accessed as just another print device and will automatically print to the first
available member.
We concentrated so far on submitting items to the queue via the
lpr utility.
lpr , especially in versions shipped with LPRng and CUPS,
allows great control over the output, enabling a user to specify printer type,
paper type, multi-page output, banners, etc.. As Linux systems became more and
more GUI oriented, several other front-end programs have arisen.
One notable example is the front-end shipped with the KDE desktop, called
kprinter(Figure 5). For the most part, kprinter
can be substituted in any instance where one would normally use lpr. Instead
of having to remember the sometimes cryptic switches, one can use menus and
shiny buttons to choose options such as multi-page output or pamphlet printing.
Figure 5:
The kprinter main screen
|
Up to this point we've shown ways of printing from Linux clients to other
devices. In this part we'll show how to configure a Linux print server to
allow Windows clients to have access.
This section provides an example of using Linux to create a PDF printer for
Windows clients. Though Linux users can easily convert documents into
PDF format, Windows users may sometimes need to purchase a commercial package
for similar functionality. The following section is based on the informative
``PDF Service with Samba'' document by John Bright.
Our first goal is to define a print queue within Samba. The main configuration
file is located in /etc/samba/smb.conf (this may vary according to your
distribution). We add the following entries to create a pdfprinter resource:
[pdfprinter]
path = /tmp
printable = yes
writeable = no
create mask = 0700
guest ok = yes
printer name = PDFPrinter
print command = /usr/share/pdfconvert
As in our LPR/LP example, we see that Samba also allows customization of the
printing script and filters. In this case, we define a pdfconvert script that will convert the input, in the form of Postscript, into the
PDF format using the ps2pdf utility. It will then drop the converted
document into an accessible part of the filesystem.
#!/bin/sh
# Simple script to convert a specified postscript file into a PDF document
# and place it in a location that is shared by the Samba server.
#
# Arguments:
# 1st - The name of the spool file
#
# John Bright, 2001, jbright@winfordeng.com
# We will create the pdf into a temporary file based upon the current
# date and time. After we are finished, we'll rename it to a file with
# the same date, but ending in .pdf. We do this because if a user tries
# to open a PDF that is still being written, they will get a message
# that it is corrupt, when it is actually just not done yet.
DATE=`date +%b%d-%H%M%S`
# Directory in which to place the output
# Be sure this directory exists and is writable by the user that Samba
# is running as (for example, the nobody user)
OUTDIR=/shr/pdfdropbox
ps2pdf $1 $OUTDIR/$DATE.temp
mv $OUTDIR/$DATE.temp $OUTDIR/$DATE.pdf
rm $1
-
- Bright
-
John Bright, http://www.linuxgazette.com/issue72/bright.html,
Issue 72 of Linux Gazette, November 2001
- CUPS
-
http://www.cups.org
- Ghostscript
-
Background information for new users of Ghostscript,
http://www.cs.wisc.edu/ ghost/doc/AFPL/7.04/New-user.htm
- LPRng
-
Patrick A. Powell, LPRng HOWTO, LPRng 3.8.15 August 11, 2002
- IPP
-
Carl-Uno Manros, IPP FAQ, April 2000
- Samba
-
The Samba Team, Samba Project Documentation , April 1, 2002
During the writing of this document I noticed that, no matter what I tried,
I could not get xpdf or OpenOffice to print any page that included any sort of
graphic. The test pages would print fine, but everything else gave a brief warning
message on the printer, then nothing. After a couple hours of troubleshooting, I
determined that the xpdf RPM was buggy. I rebuilt the package and enabled the
gzip library and everything worked as expected. To do this, download
the xpdf source RPM then install it. Change to the
/usr/src/rpm/SPECSdirectory then edit the xdpf.spec file. Look for the following line:
%configure --disable-shared --enable-static
Add -gzip to the end of the line so it reads:
%configure --disable-shared --enable-static --with-gzip
Rebuild the package using: rpmbuild -ba xpdf.spec
Finally, reinstall the new package.
Linux Printing Systems
This document was generated using the
LaTeX2HTML translator Version 2002 (1.62)
Copyright © 1993, 1994, 1995, 1996,
Nikos Drakos,
Computer Based Learning Unit, University of Leeds.
Copyright © 1997, 1998, 1999,
Ross Moore,
Mathematics Department, Macquarie University, Sydney.
The command line arguments were:
latex2html -split 1 printing.latex
The translation was initiated by Kwan Lowe on 2002-11-15
Kwan Lowe
2002-11-15