Printers

Cross-platform printer sharing in a nutshell, part 1: Getting started

This tutorial walks through the process of setting a network printer in Linux/UNIX.


One of the best arguments for creating a local area network (LAN) is the savings that sharing a printer generates. Just think about how much it would cost your company to give each user a decent printer. With Linux, it’s even better! Linux offers an ideal environment for sharing printers over a cross-platform network that includes Windows and Macintosh systems and Linux boxes. If you use Linux, you won’t have to fork over a lot of money for commercial applications and hardware that you don't need. Why pay for a pricey HP DirectJet print server, when Linux can do the job for free? Still, many people pay for DirectJet-equipped printers because they work very well on heterogeneous networks in which Linux, UNIX, Windows, and Macintosh users need to access printing services. As you'll learn in this Daily Drill Down, however, Linux can perform this job just as effectively.

In this two-part series, I’ll explain how you can make your printers accessible to all of the users of your network, including those who use Linux, Windows, and Macintosh machines. This week, I’ll show you how to implement printer sharing in the native Linux environment. Next time, I’ll discuss Windows and Macintosh users. I’m going to assume that you've already installed at least one printer on your Linux system successfully and that it's working just fine. If you haven't done so, install one now! Most of today's Linux distributions come with reasonably user-friendly printer configuration utilities, such as Red Hat's printtool. If you're using a distribution other than Red Hat, check your distribution's documentation and find out how to install a printer on your system.

Introducing the Line Printer Daemon (lpd)
Although some Linux distributions offer alternative printer interfaces, the most common one is the Line Printing Daemon (lpd). Derived from the Berkeley Software Distribution (BSD) daemon of the same name, lpd waits until printer services are needed. When an application requests printing services, lpd springs into action. It writes the print output file to a temporary storage area in /var/spool/lpd. Then, it locates the printer and parcels out the print output at a pace that the printer can handle. If lpd receives additional printing requests before the first job is finished, the daemon creates a print queue, a list of files that are waiting to print. Since different printers have different characteristics, how does lpd know how to print the file? The answer lies in /etc/printcap, the lpd configuration file. In this file, you'll find one or more stanzas, which are blocks of configuration commands that look like the stanzas of a poem. Each stanza defines a specific printer and provides such information as how the printer is connected to the computer and which filter should be used. A filter is a file that’s unique to each brand and model of printer. It defines a printer's characteristics and capabilities.

Just remember that lpd is a network service. This fact is true even if you're using Linux as a standalone, single-user workstation. When an application needs lpd's services, it routes a request through TCP/IP. Thus, if a local application can request services from a local copy of lpd, then any application on the network can do the same thing. If you configure the server and clients correctly, network printing becomes completely transparent to the user.

If you're coming to Linux from a Windows networking background, you might assume that it's necessary to implement Network File System (NFS) services on the server or clients in order to share printers on the network. With Windows, both network printing and file sharing are implemented within the same huge, complex protocol, which is called Server Message Blocks (SMB). But that's not how Linux works. In keeping with their UNIX heritage, Linux utilities are smaller, more focused, and, consequently, less buggy. NFS handles file sharing in a way that's totally independent of printer sharing. Likewise, lpd handles printer sharing without using or needing NFS.

Making a local printer available for network use
Before we begin, I should clarify some terms. The term server refers to the Linux system to which the printer is attached. The term client refers to a computer that will access the printer remotely. For example, in a four-computer network (where the machines are named luke, leia, yoda, and han), luke is the system to which the printer is attached. Thus, luke is the server. The others (leia, yoda, and han) will access the printer remotely; they're clients. To make a local printer available for network use, follow these steps:
  1. On the server, you need to create user accounts for each user who will be accessing the printer remotely. You also need to create a configuration file named /etc/hosts.lpd. This file will contain the aliases or IP addresses of the workstations that can access the printer.
  2. On each client, you'll need to add a stanza to /etc/printcap that specifies the printer's characteristics and indicates where the printer is located. You can use your Linux distribution's printer configuration tool, or you can configure the /etc/printcap file on each of the client systems manually.

Step 1: Preparing the server for network printer access
First, let’s focus on the server, the computer to which the printer is attached. To prepare the server for printer sharing, you must make sure that the printer is working properly on the machine to which it’s connected. Now, make sure that each user who will be accessing this printer has an account on the machine to which the computer is connected. This account must be identical to the one on the user's system. If you plan on using NFS, make sure that the accounts are identical to the last detail: username, user numerical ID (UID), primary group membership, and primary group numerical ID (GID).

On the computer that’s attached to the printer, open a terminal window and switch to superuser. Then, start a text editor and create a new file. In this file, type the aliases of all of the machines that will be able to access this printer. For instance, if you were creating a file on the server luke and you wanted to give leia, yoda, and han access to the printer, you would type the following:
leia
yoda
han


To use these aliases, all of the machines on your network must have /etc/hosts files that list each of these aliases and their corresponding IP addresses and domain names, as in the following lines:
192.168.1.10  luke.mydomain.org    luke
192.168.1.11  leia.mydomain.org    leia
192.168.1.12  yoda.mydomain.org    yoda
192.158.1.13  han.mydomain.org     han


If you haven’t set up your /etc/hosts files in this way, you can use the IP address of each client instead of the alias, as in the following lines:
192.168.1.11
192.168.1.12
192.168.1.13


Finally, you can save the file and exit.
If you've read some of the really ancient documentation that’s out there on the Internet, you may think that the proper configuration file is called /etc/hosts.equiv. Do not create or use any file by this name! It's a security hole that’s about the same size as the Grand Canyon. Basically, hosts.equiv lists the computers that should have totally unrestricted access to the server. Granting such access isn't a very good idea, even on a small network where everyone trusts each other and nobody would harm anyone else's system intentionally. But accidents happen, and when they happen, you should try to keep them from happening to all of the systems on your network. On a large network—especially on a network that’s connected to the Internet—using hosts.equiv is an open invitation to disaster. Instead, use hosts.lpd, which was developed to enable network printer access but doesn’t entail the risks that are involved with hosts.equiv.
Step 2: Setting up the clients
You need to know how to set up your clients with the printer configuration utility that came with your Linux distribution so that the clients can access the remote printer. If you're using Red Hat or a Red Hat-derived distribution, you can use the printtool utility. Other distributions offer similar utilities. Although these instructions are printtool-specific, you should be able to adapt the following steps to your distribution's printer configuration utility:
  1. Log in as the root user and start your printer configuration utility. To run printtool on a Red Hat or Red Hat-derived system, switch to superuser, type /usr/sbin/printtool, and press [Enter]. You'll see the Red Hat Linux Print System Manager.
  2. Click Add to create a new printer profile. You'll see the Add a Printer Entry dialog box.
  3. Click Remove Unix (lpd) Queue and click OK. You'll see the Edit Remote Unix (lpd) Queue Entry dialog box.
  4. In the Names area, type one or more names for the printer, separated by vertical bar characters (|). If the utility proposed a name, you may use it.
  5. In the Spool directory area, accept the proposed directory name. Note that each client will have its own local print spool for the remote printer.
  6. In the Remote Host area, type the IP address of the computer to which the printer is connected.
  7. In the Remote Queue area, type the name of the remote printer's queue. If only one printer is defined on the remote system, type lp. If the remote system's /etc/printcap file defines more than one printer, open this file and determine the name of the printer's queue (such as lp0, lp1, or lp2).
  8. Click Input Filter and select the computer type from the list. If your printer isn't on the list but it works with PostScript, choose PostScript Printer. Click OK to exit the input filters list.
  9. Click OK to confirm the network printer settings, which are saved in the form of a new stanza that’s added to /etc/printcap. If you're using a printer configuration utility other than Red Hat's printtool, make sure that the configuration settings are saved.
  10. Click Tests on the menu bar and choose Print PostScript test page. Make sure that the printer prints the page.

If the test doesn't work, you can troubleshoot the problem. First, make sure that the printer is working correctly on the server. Next, double-check your work with /etc/hosts.lpd (see Step 1 above). Did you type the computer names or IP addresses correctly? Now, double-check your work with the client configuration. Check your typing carefully. Then, try to access the printer from the user account of the person who uses the computer in question. If the remote printer works with the printtool test but not from the user's account, there's something wrong with the user's account on the server. In order to print remotely, the server must be set up with a user account that’s identical to the user's account on the client machine. If there's any discrepancy between the two user accounts, such as conflicting numerical user IDs or primary group memberships, fix it. (On Red Hat systems, you can use LinuxConf to change user account information. Other distributions use comparably user-friendly utilities.)

Repeat the above steps on all of the client machines on your network. If you run into problems getting one of the clients to access the remote printer, the problem almost certainly rests with the user's account on the server, the server's /etc/hosts.lpd file, or a simple typing error.

Looking under the hood: More about /etc/printcap
If you'd like to know more about how remote printing is implemented with lpd, take a look at the stanza that the printer configuration utility created. Don't make any changes, though, unless you're convinced that you know what you're doing. In particular, don't make any changes if the stanza was created by a printer configuration utility. Some of these utilities, like Red Hat's printtool, have their own idiosyncratic syntax rules, and your printer might not work if you make a change that violates these rules. If you must make changes to your printer configuration, run the utility again. Here's an example of a client system’s /etc/printcap stanza that accesses a remote printer successfully:
lp|grumpy|deskjet:\
:sd=/var/spool/lpd/lp:\
:mx=#0:\
:sh:\
:rm=192.168.100.34:\
:rp=lp:\
:if=/var/spool/lpd/lp/filter:


This isn't the place for a lengthy dissertation on the structure of /etc/printcap, but there are a few things that I should point out:
  • A stanza must be expressed on a single line. Since they would be almost unreadable otherwise, you can break up the line by inserting backslashes. If the printer isn't working correctly, make sure that each line of the stanza (except for the last line, of course) ends in a backslash.
  • Colons delimit the various parts of the stanza.
  • The first line names the printer and provides aliases in a list that’s separated by vertical bars.
  • Some variables are yes/no, on/off, Boolean variables. They’re turned on automatically if they’re present in the file.
  • Other variables are assignment variables, and they require an equals sign (for example, sd=/var/spool/lpd/lp). Still others are numeric variables, and they require the numeric operator (#), as in mx#0.
  • The printer named lp is the default printer. Additional printers are named lp0, lp1, lp2, etc.
  • The sd variable specifies the location of the printer’s spool directory. Although the stanza accesses a remote printer, the spool is stored locally (/var/spool/lpd/lp).
  • The mx variable specifies the maximum permissible size (in blocks) of the file to be printed. To allow any size file to be printed, use mx=#0.
  • The sh variable (if present) suppresses header printing. The header indicates the job name and the source of the printout. If you’re configuring a printer for use on a large network with many users, you may wish to print the headers so that an attendant can sort the print jobs.
  • The rm variable specifies the location of the remote printer. You can use an alias (such as luke) or an IP address (such as 192.168.1.10).
  • The rp variable specifies the name of the remote printer’s queue. Set this variable to the printer’s name as defined in the server’s /etc/printcap file. If the remote printer is named lp0 in the server’s /etc/printcap file, the print queue name is lp0, too.
  • The if variable specifies the location of the print filter that will be used with the printer in question.

Conclusion
In the next Drill Down in this series, I’ll tell you how to make your printer accessible to Windows and Mac users on your network. To do so, you must use a reasonably well-documented package called Samba, a Linux implementation of the Windows networking protocols. You also must use a relatively unknown package called netatalk, which enables Macintosh users to access Linux files and printers. Afterwards, you'll know how to implement printer sharing for all three platforms, a trick that you couldn’t pull off otherwise without spending lots of money on commercial applications. So, until then, have fun. And don't wear out your printer too quickly!

Bryan Pfaffenberger, a UNIX user since 1985, is a University of Virginia professor, an author, and a passionate advocate of Linux and open source software. A Linux Journal columnist, his recent Linux-related books include Linux Clearly Explained (Morgan-Kaufmann) and Mastering Gnome (Sybex; in press). His hobbies include messing around with his home LAN and sailing the southern Chesapeake Bay. He lives in Charlottesville, VA. If you’d like to contact Bryan, send him an e-mail.

The authors and editors have taken care in preparation of the content contained herein, but make no expressed or implied warranty of any kind and assume no responsibility for errors or omissions. No liability is assumed for any damages. Always have a verified backup before making any changes.

Editor's Picks

Free Newsletters, In your Inbox