Printers can cause quite a few problems for system administrators because the configuration and handling of a printer under Linux is considerably different than under DOS or OS/2. The unintuitive nature of the printer commands also complicates the handling of printers and print systems. Despite these quibbles, printers are quite easy to configure as long as you know a little about Linux, device drivers, and the printers you are using. Managing the printer queues is also relatively easy, but like many things in Linux, you must know the tricks to make the system work for you.
The printing capabilities of Linux are not as powerful and easy-to-use as most commercial versions of UNIX. Linux is based on BSD UNIX, which is not the most talented version with respect to printer administration. Luckily, few users use more than one or two printers in a typical parallel-port or serial-port based installation, so administration requirements are simplified enormously. When you work with large networked printer environments, however, Linux's limitations in this area are more apparent. A word of warning: Linux's printer administration routines have a reputation for quirky behavior, such as suddenly stopping the print spooler for no apparent reason!
Linux supports both parallel and serial printers, as well as network printers (available from another machine on the local area network). Most parallel and serial printers are character mode devices, although a few high-speed printers are block mode devices (although block mode printers are usually much too expensive for a small Linux-based system). Unfortunately, Linux does not have a simple-to-use printer installation and configuration utility like many UNIX versions, so you must create printer devices and files manually. (A few printer installation and configuration scripts are beginning to appear, although they are not in general use yet.)
Parallel printers are referred to as devices /dev/lp0, /dev/lp1, or /dev/lp2, depending on the number of the parallel port with which they are used. Most printers attached to a PC parallel port are attached to /dev/lp0, the first parallel device.
|Parallel port device||I/O address||DOS equivalent|
To determine the address of a parallel port, you can use a diagnostic utility (such as DOS' MSD.EXE or Norton Utilities). Some BIOS versions display port addresses when the system is booting. If you are unsure what the address is, try the parallel ports in order, starting with /dev/lp0, and see whether a printout is possible from that port.
Linux uses the mknod (make node) command to create a parallel printer device. The command to make a parallel printer device on the first parallel port (/dev/lp0) is
mknod -m 620 /dev/lp0 c 6 0
In this example, the device /dev/lp0 is created as a character mode device with major device number six and minor device number zero. (See Chapter 6, "Devices and Device Drivers" for more information about device drivers and device numbers.) Usually, minor device numbers start at zero and are incremented upwards. Because this printer is the first one added, the minor device number is set to zero. The -m option sets the file permission mask (to 620 in this case).
After you create the printer device driver file, you must change the ownership of the device driver to root, daemon, or root.daemon. The owner root is a good default value, but root.daemon is better because it adds a little more security to the ownerships by setting the owner to root and the group to daemon with a single command:
chown root.daemon /dev/lp0
After changing the ownership of the file, check the file permissions. Set them to mode 620 by using the following command:
chmod 620 /dev/lp0
The ownership root.daemon is a special Linux convention for the daemons run by root. The entry root.daemon does not appear in the /etc/passwd file, but it is legal. This syntax sets the owner and group at the same time. The owner is the first part of the entry, and the group follows a period. The entry root.daemon sets the owner to root and the group to daemon.
To configure a device other than the first parallel port (/dev/lp0), you must change the device name itself to the device number. For each possible parallel port, the mknod commands are as follows:
mknod -m 620 /dev/lp0 c 6 0 mknod -m 620 /dev/lp1 c 6 1 mknod -m 620 /dev/lp2 c 6 2
In these examples, the minor device numbers have been incremented to correspond to the port number. Although numbering the devices in this manner is not absolutely necessary, it can help with identification when you want to know which port the device is hanging off of.
After issuing the mknod and chown commands, check to ensure that the ownerships are set properly. You should also create a spool directory for the printer. The permissions and ownership requirements of the spool directory are important and are discussed in "The /etc/printcap File" section later in this chapter.
Printing services are handled by a daemon called lpd (line printer daemon). The lpd daemon is usually started automatically in the /etc/rc boot process when the system moves to multiuser mode. The lpd daemon handles a number of tasks and keeps running as long as Linux is active (unless terminated by the superuser or a daemon crash). One of the important parts of the daemon's startup procedures is to read the printer configuration file, /etc/printcap.
The /etc/printcap file is used to identify instructions for communicating with all the printers that are configured and attached to the system (in the same manner that /etc/termcap contains terminal definitions). Once it has started itself, lpd starts up two other daemons called listen and accept that handle any incoming print request.
You probably won't ever have to modify the lpd daemon. Because the Linux daemon is a little unstable, though, you may have to restart or terminate it while you make some configuration changes. To start the lpd daemon, use this syntax:
lpd [-l] [port]
The -l option starts a logging process that copies a note to a log file every time a print request is handled. Although the -l option can be useful when you're debugging a printer installation or configuration, be careful about leaving it running for too longthe log files tend to become very large. If you do keep logging active, use a cron process to clean the log file at regular intervals.
The port option of the lpd command enables you to specify an Internet port number for the daemon if you want the system default information to be ignored. You will probably never have to use this option on a stand-alone or small network, but it can be useful with very large networked printing systems (which are unlikely to be based on Linux).
When a print request is received over the network (or locally), the lpd daemon performs a short validation routine to see whether the user who sent the request is allowed to use the printer. This routine uses the /etc/hosts.equiv and /etc/hosts.lpd files. If the machine name of the sending user is not in either file, the print request is refused. Your local machine is always in hosts.equiv (as localhost), so all users on your machine can have their print requests granted.
If you have to terminate the lpd daemon, obtain its process ID number using the ps command, and then issue a kill command with that process number. Chapter 20, "Processes," explains these steps in more detail. When the lpd daemon is terminated, no print requests are accepted.
When a print request (often called a print job) is received by lpd (or its associated listen and accept processes), the pages to be printed are copied to another area, called the print spool area, of the filesystem. This action frees up your console when you issue a print request and enables you to continue to make changes to the files you want to print after they have been sent to the daemon.
In most cases, the print spool area is in the /usr/spool/lp directory. Under this spool directory, each installed printer has a dedicated directory, which is usually given the printer's name specified during the printer installation routine. For example, a printer called hplaser uses the spool directory /usr/spool/hplaser. All the print requests for each printer are stored in its directory. In this directory, each request is assigned a unique filename and a print request identification number. The daemon for this printer adds the print request number to a queue and notifies you of what the number is. You can then use the print request identification number to check the status of the print request or remove the request from the queue.
Some versions of Linux let you set the size of the print spool area though an entry in the minfree file in the spool directory. The minfree file gives the number of disk blocks (usually a block is 1K) set aside for spooling requests. You can change the minfree file with any ASCII editor. If you have lots of disk space, you needn't worry about this value because the spooler will use available space as necessary. If you are tight for disk space, though, you may want to reserve a little space for the spooler that can't be used for other reasons. The size of the disk space reserved for the spooler should be dependent on the number of users and the amount of printing they will do. A good rule of thumb is about 100K per user for normal use.
Each printer's spool directory may contain two special files called status and lock. Each file is one line long and can be modified with an ASCII editor. The files contain a description of the current state of the printer. The lpd daemon creates and manages these files, which several printer commands use display status information to the user.
This section follows a typical print request through the print system so you can see how the printer daemons work and how Linux handles each stage of the request. When you issue a print request with a print command (such as lpr), the command generates output for the printer to print. The command then copies that output into the queue in the spool directory for the printer you have requested.
You can specify the printer destination on the print command line or set a default printer name as an environment variable so the system always knows which printer to use. After determining the destination printer name, lpr checks the file /etc/printcap for the printer's configuration information (including the spool directory name).
The lpr program is the only one in the Linux system that can queue files for printing. Any other program that offers printing capabilities, including most editors and word processors, executes the print request by calling lpr.
As part of the spooling task, lpr checks for any special instructions on how to print the file. These instructions may refer to fonts, paper sizes, colors, processing languages, or any other printer configuration information. Printer instructions can come from the command line (in the form of arguments you provide with the print command), from environment variables (set up by the shell's startup files or you), or from the system's default values.
When the print request is copied into the spool directory, lpr creates two files. One file has the letters cf (control file) followed by the print ID number. This cf file contains information about the print job, including the owner's name and special printing instructions such as line spacing or paper selection. The other file starts with the letters df (data file) and holds the contents of the file to be printed. After lpr creates the df file, it sends a signal to the lpd daemon that indicates that a print job is waiting in the spool directory. The lpd daemon then starts a daemon to handle the printer's queue (if one isn't already running). A daemon is present for every printer queue as long as there is something to print. When the print queue is empty, the printer daemon terminates.
After lpd gets the print job signal from lpr, it checks the file /etc/printcap to see whether the printer is a local or remote printer. For remote printers (one attached to another machine on the network), lpd starts a network connection to the remote machine and transfers both the control and data files to the remote's spool directories and informs the remote machine's lpd daemon that a print request is queued. To end the process for a remote print request, lpd deletes the local copies of the cf and df files. For local printer requests, lpd checks to make sure the printer exists and is enabled, and then sends the print request to the daemon running that printer queue. Once the files have been printed, they are deleted from the spool directories.
As you have seen already in this section, the /etc/printcap file is used by both the print commands (such as lpr) and the lpd daemon. The /etc/printcap file contains information about every printer that is accessible from the Linux machine, including all remote printers that have been configured on the local machine. The following extract from the /etc/printcap file for the Hewlett Packard LaserJet 4M laser printer shows the straightforward format of this kind of file:
# HP Laserjet lp|hplj|hplaserj-tparker|HP LaserJet 4M next to the water fountain:\ :lp=/dev/lp0:\ :sd=/usr/spool/lp/lp0:\ :lf=/usr/spool/lp/errorlog:\ :mx#0:\ :of=/usr/spool/lp0/hpjlp:\
Comments anywhere in the information are identified by a pound sign (also called a hash mark) in the first column. The first field in each printer's entry is a list of all the names users can use to refer to the printer. These names can be used with environment variables and as options on the lpr command line. All the valid printer names are separated by a vertical bar. Usually each entry has at least three names: a short name that is four characters or less (such as hplj), a more complete name with an owner, if necessary (such as hplaser-tparker), and a full descriptive name with any other information necessary to identify the printer to a user (such as HP LaserJet 4M next to the water fountain).
If a print job is submitted without a destination name and one cannot be determined from environment variable values, the job is routed to the Linux system default printer name lp. Therefore, one of the printers (usually the system default printer) should also have the name lp as part of its identifying names in order to prevent error messages.
Following the printer name is a set of two-character parameters and values used to define configuration information about the printer. The format of these entries follows one of the following models:
|NN||A Boolean value|
|NN=string||Set equal to string|
|NN#number||Set not equal to number|
Most assignments in this area of the /etc/printcap file are shown with colons beginning and ending each definition to enhance readability (and make the file easier for the print utilities to parse for information). Null values are allowed; you can create them by putting two colons together with no space between them.
When you use a Boolean value (with no assignment following the two character identifier), the value is set to True by default. If you want the vaule to be False, don't include the two-character identifier in the description. You use Booleans to specify simple information, such as printer control language support.
As with terminal definitions in the /etc/termcap file, many codes are allowed in the /etc/printcap file. A few of the more important and prevalent parameters are worth mentioning as they are useful for administration purposes:
|sd||The spool directory|
|lf||The log directory for error messages|
|af||Accounting log file|
|mx||What type of files can be printed|
|of||Output filter program to be used when printing|
Not all these parameters need to be present in every printer definition in the /etc/printcap file, but they are likely to be present as they provide basic information.
The sd parameter specifies the spool directory for the printer. As mentioned earlier, all printers should have their own spool directories. The spool directories are usually composed by taking the printer name and creating a directory with that name under the /usr/spool directory, such as /usr/spool/lp/hplj and /usr/spool/lp/epson. Spool directories are necessary for both remote and local printers.
When you add a new printer is added to the system, you may have to create a spool directory manually by using mkdir. Set the permissions for the spool directory to 775. The directory must be owned by root or daemon, and you should set the group ID to root or daemon as well. In both cases, daemon is arguably the better ID for user and group, although root works fine (but may pose a very slight security problem).
The lf parameter specifies the log directory for error messages. You can put the printer error log file anywhere on the system, although most Linux systems have it in the /usr/spool/lp directory for easy access. All printers can share the error log, as each log entry includes the name of the printer. Putting all the error messages in one directory makes it easier to clean up the log files on a regular basis.
A printer accounting log file, as specified by the parameter af, is used to record the number of printouts sent by a user on systems where users are charged for printing. When an accounting file is used, an entry is written to the accounting log file after a print job is finished. If the system doesn't use accounting records (most Linux systems don't), you can ignore the accounting log file entry in the /etc/printcap file, although you may want to have the accounting file active for statistical purposes. You can display account information with the Linux pac command. Use the man pac command to display the man pages for more information about pac.
The mx parameter enables you to identify the types of files to be printed. Usually this parameter is set to mx#0, meaning that there are no restrictions on the types of files. You may want to restrict the type of printing on some lasers or inkjets that have high per page costs, for example, or prevent pages with color instructions from being printed as grayscales on a monochrome laser printer.
You use output filters, specified by the parameter of, to modify the format of the outgoing print file to fit the printer. For example, a common output filter changes the number of lines per page. Many laser printers can't handle 66 lines per page, so the output filter repaginates output to 60 lines per page (or whatever the number of lines per page is set to). Sometimes special codes must be added to force line feeds, font changes, or paper bin selections. All these items are part of the output filter. Several other types of filters are available, but the output filter is the most common.
Linux systems control printers through a utility called lpc. The lpc program enables you to do several important functions involving the printers on your Linux system:
You cannot use the lpc program for remote printers. It only affects those printers directly attached and configured on the local machine. If you must manage a remote printer, log into the remote machine as root and make the changes through that login.
The lpc utility is one of the most unpredictable and unreliable programs included with the Linux operating system. It can hang up for no obvious reason and can display faulty status messages.
When executed on the command line without any arguments, lpc prompts you for a command. The following list summarizes all the valid lpc commands and their arguments (a vertical bar indicates a choice of arguments):
The lpc utility is not very user-friendly, but it is the only way to handle the printers and their queues in Linux. Several front-end menu-driven utilities are beginning to appear that simplify this task, but they are of variable quality and are not widely available.
Instead of totally relying on the lpc command, you can use the several commands that help you administer the printer queue directly. These commands are designed to simplify the two tasks that are commonly required by a system administrator: displaying the current queue and removing print jobs in a queue.
To display the current print queue for any printer, use the lpq command. It has the following syntax:
lpq [-l] [-Pprinter_name] [job_ID ...] [username ...]
With no arguments, lpq displays information about the current printer queues. The lpq command normally displays information about who queued the print job, where it is in the queue, the files being printed, and the total size of the files. The -l option displays more information about each entry in the printer queue. Usually only one line of information is displayed.
You can display a specific printer with the -P option followed by the printer's name. If no name is supplied, the default system printer is displayed. If one or more job_IDs or usernames are provided, only information about the specified jobs or jobs queued by the specified user is shown.
To remove files from a printer queue, use the lprm command. This command is often mistyped as lpr, which does not remove the file from the queue. To use lprm, you must know the print job ID, or, if you are logged in as root, you can remove all jobs for a particular printer. The syntax of the lprm command is as follows:
lprm [-Pprinter_name] [-] [job_ID ...] [username ...]
If the single hyphen argument is used, lprm removes all jobs owned by the user who issues the command. If you are logged in as root and issue this command, all print jobs are removed.
You can remove a particular printer's jobs by using the -P option. For example, the command
lprm -Phplj -
removes all print jobs queued on the printer hplj by the user who issues the command or all print jobs for that printer if the command is issued by root. If a print job ID or a username is supplied as an argument, lprm removes the specified job or all jobs submitted by the specified user. If no arguments are supplied, the currently active job submitted by the user is deleted.
It is easy to accidentally remove all print jobs for a printer when you use the lprm command while logged in as root. Take care to use the proper syntax.
When lprm removes files from the queue, it echoes back a message to the display. If there are no files to remove, nothing is echoed back (and you will be left wondering what, if anything, happened).
Because users cannot access the Linux printer spooling directories, they can only remove queued print jobs with the lprm command. If you are a system administrator, you may want to let all system users know how to use this command to save unwanted print jobs from printing.
If you try to use lprm on a job that is currently being printed, it may not be terminated properly as the file may already reside in the printer's buffer. In some cases, terminating a job that is currently printing can cause the printer to lock because some output format files cannot handle the termination instructions and freeze when the lock file in the spool directory changes. In cases like this, you must use the ps command to find the output filter process ID and then kill that filter.
When you have a printer lockup problem that doesn't solve itself when you use the lpc utility, try killing the lpd daemon and restarting it. If that doesn't work, you probably have to reboot the entire system.
Handling printers on a Linux system is not onerous, as long as you know the commands and processes that perform the daily tasks you need. Installing the printer is quite easy, although you have to be careful to set the permissions and ownerships properly. Once installed, printers tend to be either trouble-free or troublesome. All you can do is hope for the former!