home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam    

Book HomeRunning LinuxSearch this book

9.5. Printing

The lpr command prints a document on Linux. You might not always invoke this command directly--you may just press a Print button on some glitzy drag-and-drop graphical interface--but ultimately, printing is handled by lpr and the other print-management utilities we'll describe here.

If you want to print a program listing, you might enter:

lpr myprogram.c

Input is also often piped to lpr from another command, as we will see later. lpr starts the printing process by storing the data temporarily to a directory called a print spool. Other parts of the print management system, which we showed you how to set up in the section "Section 8.4, "Managing Print Services"" in Chapter 8, "Other Administrative Tasks", remove files from the print queue in the correct order, process the file for printing, and control the flow of data to the printer.

There is at least one print spool for each printer on the system.[40] By default, lpr looks for a printer named lp. But if you need to specify a printer of a different name, just include a -P option.

[40]A printer that can be used in different modes of operation, such as for printing faxes as well as letters, may have a separate print spool for each purpose.

For example, to send your document to a printer named nene, enter:

lpr -Pnene myprogram.c
If you forget the name of a printer, you can look at the names of the spool directories under the /var/spool/lpd directory or at the /etc/printcap file entries to see all the names recognized for each printer.

If you want to use a particular printer for most of your printing needs, you can also set it in the PRINTER environment variable. So, assuming that you are using the bash shell, you could make nene your personal default printer by putting this command in your .bashrc file:

export PRINTER=nene
The -P option in lpr overrides the PRINTER variable.

Once you know how to print a file, the next problem you might face is finding out what is happening if your file doesn't instantly print as you expect. You can find out the status of files in the print queue by using the lpq command. To find out the status of files sent to your default printer (the PRINTER environment variable applies to all the commands discussed in this section), enter:

$ lpq 
nene is ready and printing
Rank   Owner      Job  Files                                 Total Size
active lovelace   020  (standard input)                     776708 bytes
1st    parcifal   024  (standard input)                    2297842 bytes
1st    lark       023  (standard input)                      10411 bytes

You see that the printer is running, but there are large jobs queued ahead of yours (if you are lark). If you just can't wait, you might decide to remove the job from the print queue. You can use the job number of the printing task that lpq reported to remove the printing job:

$ lprm 23 
023 dequeued
023 dequeued
The spooled print file identified as job 023 is discarded, along with an associated file that contains instructions for formatting the file.

You can narrow the lpq report by asking about a specific print job by task ID (rarely used), by printer, or by user ID. For example, to get a report that identifies spooled files sent to a printer named ada you would enter:

$ lpq ada
ada is ready and printing
Rank   Owner      Job  Files                                 Total Size
active lovelace   788  standard input                        16713 bytes
1st    lark       796  standard input                        70750 bytes

If you are the root user, you can kill all pending printing tasks by entering the command:

lprm -
If you are not the root user, issuing that command kills only the printing tasks you own. This restriction also holds true if you specify a printer:
lprm ada
If you are root, the ada print queue is emptied. If you are a normal user, only the print files you own are removed from the specified print spool. The lprm utility reports on the tasks it kills.

The root user can kill all the print tasks issued by any user, by specifying:

lprm username

If you issue lprm with no argument, it deletes the currently active print jobs that you own. This is equivalent to entering:

lprm yourusername

If you want to see whether a printer is down, you can use the lpc command:

/usr/sbin/lpc status ada
See the section "Section 8.4.12, "Controlling Printer Services with lpc"" in Chapter 8, "Other Administrative Tasks" for details. The lpc utility is usually installed in the /sbin or /usr/sbin directory.

Now for some more examples of common printing tasks and filters you can use.

To get a quick hardcopy printout of the printcap manual page, enter:

man printcap | col -b | lpr
The man command finds, formats, and outputs the printcap manual page in an enriched ASCII output that uses backspaces to overstrike and underline characters (in place of italics) for highlighting. The output is piped through col, a Unix text filter, where -b specifies stripping the "backspace" instructions embedded in the man page which results in simple text strings, still maintaining the layout of the formatted man page. The output of col is piped to lpr, which spools the text in a spool directory.

If you want to simulate underlining, you could instead use a filter designed originally for formatting print to a text display:

man printcap | colcrt | lpr

Suppose you want to print the fully enriched man page with highlighting and all. You might use a command like this:

groff -man -Tps /usr/man/man5/printcap.5 | lpr
The groff command applies the man macros to the file specified, creating PostScript output (specified by -Tps); output is passed to lpr, which spools it, and lpd applies the default print-processing instructions from the /etc/printcap file.

Most Linux installations use BSD-style print utilities developed for the Berkeley Software Distribution of Unix. If you find utilities named lp, lpstat, cancel, and lpadmin, your Linux host has a System V-based print system. You need to read the manual pages and perhaps other documentation for that package. There are other printing systems that could be installed on your system, such as the PLP package, but we only document the usual Linux BSD-based print-management utilities here. We also describe how to use some of the other commonly installed print support utilities for Linux, such as filters that prepare documents in special ways to print on your printers.

The BSD-style print-management system is traditionally called "lp" after the line printers that were the standard print devices of the era in which the package was developed.[41] In the Linux community, the BSD print management package is more commonly usually called "the lpr package." Of course, the lpr command is only one tool in the package.

[41]Don't be misled if you hear someone use the term lp, which is a confusing misnomer. There is no lp utility in the BSD print-management package, but there is one in the later-developed System V print package. It is still possible that your BSD package allows you to use an lp command in order to print, though. Some systems use a shell script (filter) named lp to convert lp command options into lpr command options, and pass them on to lpr. This is solely for the convenience of users that are familiar with the System V lp command.

9.5.1. What Happens to a File After It's Put on the Queue

Only the root user has the ability to access printers directly, without using the printing system. (That's not a wise thing to do, by the way.) Linux doesn't grant system users the ability to address various physical devices directly, because crippling conflicts could result, and also because it's just too much work for them to bother with. Instead, utilities call background system processes to schedule your printing among other tasks, convert source file data to print to a specific printer using its printer language and protocols, set print resolution and format the pages, and add (or know not to add) header and footer data and page numbering. Linux configures itself to handle its physical devices when it is booted, including setting up ports and protocols to handle printing.

The print-management system is controlled by lpd, the "line printer daemon," which has necessary privileges to access printers for you. Once the print management system is installed, lpd is started every time the Linux system is initialized (booted). The /etc/printcap file provides the control information lpd needs to manage the files you print.

Here's what the printer-management system is actually doing when you enter a printing command. When called, lpr checks whether you have a PRINTER environment variable set. If you do, lpr loads the print options stored there as instructions to process the print file it is receiving. Next, lpr applies any option parameters you gave it or that are passed to it by a program that preprocessed the file. Last, lpr sends the file to the spool directory for the printer that will be used, along with another temporary file that stores the processing specifications for lpd to apply. Then lpr notifies lpd that there is a print file spooled. If lpr receives an option it doesn't understand, it passes the option on to the print filter, which we'll discuss shortly.

When lpd finds a job in the print spool, it reads the processing specifications (which tell it how to pass the print file through filters and direct the output to a device) and completes the printing task, erasing the print file and processing file when the printer has received all of the processed print file.

All Unix printing systems process a file through at least one filter to prepare it for output. This filter processes the file using any of the usual options that Unix print utilities pass to it.

Appropriate filters are set up by the administrator and specified in the printcap file to meet your usual printing needs. If you want to do any special processing, you give your processing instructions as options to the print commands. Your instructions enter the printer management system through the lpr command (directly on the command line or passed indirectly by some other command). The lpr command spools the print file in the correct print spool directory and stores the related processing instructions in an associated file in the same print spool.

When it is time to print your file, the lpd daemon reads any special processing directions for the print file, which may override default processing directions set in the /etc/printcap file. When lpd passes your file to the correct filter for the printer you are using, it also passes along any instructions it did not act on. The filter then further processes the file itself according to the instructions or calls yet other filters to perform the processing it could not. The file is then passed on to the printer by lpd. You can see that this hidden filter provides most actual control of print formatting.

If you have special printing requirements, you need to learn the options to pass to the filter that control print formatting. The standard options are discussed in the lpr manual page. Additional filter options are documented in the filter package that is used. Later we discuss a couple of filters that are probably on your system. We can't possibly describe how to use all the filters and filter packages available to you for use with Linux. You should read the manual pages for the filters on your system to learn how to get the output you want.

A well-configured printcap file uses the printer's name to determine what kind of filtering to apply. For example, if your printer can automatically format and print an HTML (World Wide Web) document, you may be able to tell lpr to print to the html printer:

lpr -Phtml ~/homepage.html
This printer could actually be the same printer you use for PostScript, for example, but by specifying a printer named html you cause lpd to use a different printcap definition that processes the file through an HTML filter into a graphic format the printer understands.

Since the system administrator controls the contents of /etc/printcap, you are not at liberty to simply exchange one filtering process for another. You do have a lot of control on the command line and through environment variables that affect your typesetting tools, filter parameters, and printer selection. When necessary, you can filter files before submitting them to the printer management system. For example, if you receive email with an attached graphic that you cannot display or print, you might save the file to disk and then use one of the many graphic conversion utilities available for Linux to convert it (filter it) into a printable form, before passing the file to lpr.

Much depends on the cleverness of the filter. If an option is passed through lpr and the filter but is never interpreted, it may end up passed through to the printer, either before or after the actual print file. This may have no effect. In some cases, a printer configuration command is deliberately passed to the printer this way. More typically a passed option prints extra pages, probably with stray characters on them; usually this is harmless. If you observe such behavior, make sure you aren't causing the problem yourself with environment variables, badly formed commands, or unsupported options. If it wasn't your fault, the administrator should try to trace the problem to save paper and time.

Some filters automatically apply the PRINTER environment variable if you set it. You should know that the equivalent printer variable for a System V print system is LPDEST, and some print filters you acquire may expect or accept that variable. You may even work on a mixed network with accounts on different systems where one uses BSD print management and another uses System V. If you are a belt-and-suspenders kind of person, you can set both LPDEST and PRINTER in your shell initialization file.

Problems using a print filter may affect other users on a multiuser system. Report any difficulties to the print-system administrator.

9.5.2. nenscript

The nenscript utility is a flexible filter that provides good formatted output for PostScript printers, even from ASCII text files. It isn't a basic Linux utility, but it is included in a number of Linux distributions and can be retrieved from the usual Linux FTP sites. While you can invoke nenscript to send a prepared file to the printer, it usually is specified in the /etc/printcap file as a pass-through filter that takes text from the standard input and sends it to the standard output.

Suppose you are printing out a C program and want line numbering and a printout on green-striped fanfold paper (not the same format you'd want when printing those graphics you downloaded from the Internet on your nifty PostScript printer). You need to have the program processed, and then insert the line numbers in front of the lines. The solution is to process the file through a filter such as the nenscript utility (if you have it installed). After doing its own processing, nenscript passes the file to lpr for spooling and printing to your trusty tractor-feed printer (named dino here):

nenscript -B -L66 -N -Pdino myprogram.c

The nenscript filter numbers each line of the file passed through it when you specify the -N option. The -B option suppresses the usual header information from being printed on each page, and the -L66 option specifies formatting at 66 lines per page. The nenscript filter just passes the -Pdino option through to lpr, which interprets it and directs the output to dino's print spool directory for printing.

When called on the command line, nenscript automatically passes output to lpr unless you specify standard output by supplying the -p option. You don't need to pipe or redirect nenscript output to lpr explicitly.[42]

[42]The nenscript utility could also be the usual filter that the printcap file specifies for use with your printer. It won't hurt for the file to go through a properly designed filter more than once. A filter passes a processing instruction on only when it does not perform the processing itself. As a filter executes an instruction, it discards the processing option. You needn't worry that your file will end up with two sets of line numbers on the page.

Suppose you are going to print a lot of program listings today. For convenience, you can set an environment variable for nenscript to specially process and print your listings each time:

export NENSCRIPT=" -B -L66 -N -Pdino"
Now, to print your listing correctly, all you need enter is:
nenscript myprogram.c

nenscript optionally sends output to a file, which is often useful for preparing PostScript files on Linux hosts that don't actually have a PostScript printer available. For example, to convert a text file to a PostScript file, formatted for two-column printing on A4 pages in 6-point Courier font, for instance, you would type:

nenscript -2 -fCourier6 -TA4 -pdocument.ps document.txt

The -2 option overrides the one-column default, and the -fCourier6 option overrides the 7-point Courier default for two-column output. (The one-column default is Courier10; nenscript always uses Courier font when converting plain text into PostScript.) The -TA4 argument specifies European standard A4 paper format. If nenscript was compiled using the US_VERSION variable, the default paper format is 8.5 x 11 inches (if you're not using the US_VERSION environment variable, you can specify this size through -TUS). The -p option specifies that the output should be stored to document.ps, and the filename specified with no option is the input to nenscript. If no filename had been specified, nenscript would have taken standard input as the filename.

As another example, to print the nenscript manual page as basic text on a PostScript printer, enter:

man nenscript | col -b | nenscript

The man command retrieves and formats the manual page and formats it for text display. The col -b command strips the backspace instructions for highlighting and underlining, leaving plain text that is piped to the nenscript filter. This turns the plain text into simple PostScript with some "pretty printing" that applies headers, footers, page numbering, and the like. Finally, the file is passed to lpr, which spools the file. The file passes once more through the filter specified in the printcap file, which could be a "dummy" filter that simply passes the text through. Or the filter could do additional things, such as attaching a formfeed character to the end of the print file.

If you specify the -Z option with nenscript, it attempts to detect PostScript files passed to it and passes them through unaltered.

If a PostScript file is passed to nenscript and is taken for a text file (probably because nenscript was not called with the -Z option) nenscript will encapsulate    it and pass it through to print. This can result in the PostScript code being printed out literally. Even a small PostScript file can use up a lot of paper in this way.

Suppose the lpd daemon already applies nenscript to process files sent to the printer. The file should still process correctly if it does, but intervening filtering could cause the second pass through nenscript to encapsulate the PostScript source. It would be safer to set the NENSCRIPT variable. When the nenscript filter is applied by /etc/printcap to a print file, the options set in your NENSCRIPT environment variable are used, but are overridden by explicit options passed through lpr from a command line or another utility.

Note that you could specify the default printer to use either in PRINTER or as a -P argument stored to NENSCRIPT. If you set NENSCRIPT to specify a printer to use, that printer will be used every time NENSCRIPT filters one of your files. We recommend that you set PRINTER rather than -P in NENSCRIPT, so that you can change the printer specification and have it filtered appropriately.

Library Navigation Links

Copyright © 2001 O'Reilly & Associates. All rights reserved.