12.5 CUPS

12.5 CUPS

With these preliminaries out of the way, let's look at CUPS. CUPS has several interfaces, including a Web-based status and administration tool. The Web interface is very good for normal maintenance and operation, but unfortunately, if your needs lie outside the abilities of the interface, you still have to know how the system works and where the various configuration files reside.

You can install CUPS anywhere you like. Most distributions use a /usr installation prefix, so the clients are in /usr/bin, the system programs are in /usr/sbin, and so on. This book assumes that your directory prefix is /usr. Here are the directory locations and contents:

  • /usr/sbin The cupsd server and administration programs

  • /usr/bin User-level clients, including lpr and lp substitutes

  • /etc/cups Configuration files

  • /usr/lib/cups Filters, backends, network frontends, and Web interface scripts

  • /var/log/cups Printer log files

  • /var/spool/cups Spooled print jobs

  • /usr/share/cups PPD file sources, fonts, and other program data

  • /usr/share/doc/cups Online documentation

12.5.1 Configuring cupsd

The central server and scheduler in CUPS is named cupsd, and the central configuration file is cupsd.conf. You normally do not need to do anything to get a working cupsd, but a stock configuration file isn't usually very secure (see Section 12.5.2).

Examine the configuration file to get an overview of the things you can change. If you have ever configured the Apache Web server, you will immediately observe similarities between the httpd configuration files and the CUPS files.

Your cupsd.conf file contains a lot of information, but first look for the AccessLog path and change it if you want the log file in some other place:

AccessLog /var/log/cups/access_log

The default IPP port is 631, so you should see the following line:

Port 631

You should not need to change this. However, you may wish to add more ports with the Listen keyword.

The following parameters select the user and group that run all tasks except the cupsd server. You likely do not need to change these, but you may need to add the user and group to your system:

User lp
Group sys

12.5.2 CUPS Security

Before you start CUPS, you should get a handle on security matters. Configured and installed from source code, CUPS does not have an enviable level of security, and you should do something about that before you even start the server. If your CUPS installation came with a Linux distribution, you should still take a look through this section to verify that you have a practical level of security.

This section covers how to configure digest authentication, the most useful type of authentication available for the CUPS Web administration interface. Run through the following steps on a new installation:

  1. Scan your cupsd.conf for a section that looks like this:

    <Location /admin>
    AuthType Basic
    AuthClass System
    ## Restrict access to local domain
    Order Deny,Allow
    Deny From All
    Allow From
    #Encryption Required
  2. Change AuthType Basic to AuthType Digest. Basic authentication sets up a Web browser to send Unix user passwords as plain text. As earlier in the networking chapters, this is a really bad idea.

  3. Run the following command to add an admin user to the CUPS digest password file (/etc/cups/passwd.md5):

    lppasswd -a admin
  4. When prompted, choose a password containing at least six characters and one number.

Certificate Authentication (for Command-Line Utilities)

You are now set up to use the CUPS Web interface securely. However, you will inevitably turn to command-line administration programs such as lpadmin when managing CUPS. These utilities also require authentication because they operate through the same network port as the Web interface. However, you may notice that you don't need a password to run these command-line programs as the superuser. Why is this so?

The answer is that CUPS has another form of authentication called certificate authentication, used primarily by the command-line programs and internal server communication. The CUPS scheduler places identifiers in the certificate directory /etc/cups/certs for various purposes, but the one you care most about is /etc/cups/certs/0. Any user that can read this file can run administrative programs without a password, because these programs send the certificate instead of a username and password.


Don't use chmod to allow administrative access for non-root users because you may inadvertently allow administrative access for anyone on the system. Instead, add the desired users to the Unix group specified by the Group directive from Section 12.5.

12.5.3 Starting CUPS

With your security situation now under control, you're ready to start the CUPS scheduler and add some printers. To start CUPS, all you need to do is run cupsd as the superuser. If you compile CUPS from source code, you should take careful note that the install procedure modifies your init.d and rc.d boot directories to make CUPS part of your startup sequence.

To test your installation, access the Web interface by pointing a Web browser to CUPS at this URL (notice that this is the IPP port on your machine):


This should yield a screen with several printing options. There are no printers in a new CUPS installation, so adding a printer is your first order of business.

12.5.4 Adding and Editing Printers

The easiest way to add a printer is with the Web interface (there is an Add Printer button on the printer list page). The first time you try to do any administration task, CUPS asks you for a username and password. Use the admin user and password that you configured in Section 12.5.2.

To add a printer with the command-line interface, use the lpadmin command. The bare minimum command for adding a printer without a print filter is as follows:

lpadmin -p name -v device

Depending on your configuration, you may need the -E option to specify encryption.

Adding a Test Printer

As is the case with most Unix utilities, commands like lpadmin do nothing more than modify text files (except that with CUPS, lpadmin opens a network connection to the CUPS server, sends some data, and then the server changes the files). You should know exactly what happens when you run lpadmin.

Add a dummy test printer by going through the following steps:

  1. Run lpadmin to add the printer:

    lpadmin -p test -v file:/dev/null
  2. Use lpstat to verify that the printer is there:

    lpstat -p

    Your new printer should show up as follows:

    printer test disabled since Jan 01 00:00 -
            reason unknown
  3. Examine /etc/cups/printers.conf. You should see an entry like this:

    <DefaultPrinter test>
    Info test
    DeviceURI file:/dev/null
  4. Activate your printer:

    lpadmin -p test

    The lpstat -p command should now report the printer as idle rather than disabled.

  5. Send a test job to the printer:

    echo test | lp -d test
  6. Verify that the job started by looking at /var/log/cups/error_log. The file-name is somewhat misleading, because error_log also contains normal diagnostic messages. You should see some entries that look like this:

    I [05/Oct/2003:14:44:46 -0700] Started "/usr/lib/cups/cgi-
    bin/printers.cgi" (pid=17156)
    I [05/Oct/2003:14:46:23 -0700] Adding start banner page "none" to job 1.
    I [05/Oct/2003:14:46:23 -0700] Adding end banner page "none" to job 1.
    I [05/Oct/2003:14:46:23 -0700] Job 1 queued on 'test' by 'user'.
  7. The job should also complete. Use the following command to make sure this is the case:

    lpstat -W completed -l test

    The output should look like this:

    test-1                  user               1024   Sun Oct  5 14:46:23 2003
           queued for test
  8. Remove the test printer when you're finished by using this command:

    lpadmin -x test

This lengthy procedure confirms that your CUPS server is running and that you can add and modify printers.

Adding a Real Printer

Now that you have some familiarity with the process, you are ready to add a real printer with a particular model using this command:

lpadmin -p name -v device -m model

The model parameter is extremely important because it provides printer-specific information, including the printer driver specification. If you do not use the -m parameter, CUPS uses a "raw" print model, sending unfiltered input directly to the printer. You almost certainly do not want this, because printers can generate copious amounts of garbage upon receiving bad input.

If you want to make the new printer the default, run this command:

lpoptions -d name

For the most part, you provide a PostScript Printer Description (PPD) filename as model. You can get a list of PPD files with this command:

lpinfo -m

However, in a stock CUPS installation, it's unlikely that the output list will contain an appropriate PPD entry for your printer, even though some of the entries may look tempting. Before discussing PPD files (see Section 12.5.6 for more information on those), let's briefly look at how to specify a device for the -v option in the earlier lpadmin command.

12.5.5 Printer Devices (Backend Specifications)

As you might surmise from the file:/dev/null specification in the test printer you created, you specify devices with Uniform Resource Identifiers (URIs). You can get a partial list of URI options with the lpinfo command:

lpinfo -v

The output looks something like this:

network socket
network http
network ipp
network lpd
direct parallel:/dev/lp0
direct scsi
serial serial:/dev/ttyS0?baud=115200
serial serial:/dev/ttyS1?baud=115200

The right-hand column contains backend types and complete URIs. You might see the following backends:

  • parallel Most direct connections are still through the parallel port. The port named LPT1 in DOS and Windows is /dev/lp0 on Linux, so the following device specification works fine in most cases:


    However, you may want to use the bidirectional capabilities of the port for PostScript printers. For example, you may want an accounting program to ask the printer how many pages it prints for each job. Use this device for the bidirectional parallel port:

  • usb Newer printers with USB connections use a slightly different backend than parallel ports do. The URI looks something like the following, although the device filename may not be the same on your system:

  • socket This is a direct TCP network connection to the print engine of a network printer. Most of these printers listen on TCP port 9100, so you can specify this as follows (since port 9100 is the default, you don't really need the :9100):

  • lpd If you want CUPS to send jobs to the Berkeley LPD port of a remote print server or printer, use this URI specification:

  • smb This is for printing to a Windows printer share. You need to use Samba's smbspool program in this case. See Section 14.6.2 for more details on the URI specification and setting up the Samba backend.

  • ipp, http These are for printing to other network IPP servers (such as remote CUPS servers). Here is an example:

  • serial In the earlier days of Unix, machines talked to printers with a serial port, and some special-purpose printers still have serial ports. Because serial ports have a more complex system configuration than parallel ports, you often need special parameters to indicate the baud rate and other port settings. At the very least, you should specify the baud rate, as in this example:


    However, you often need to specify the parity and flow-control settings. Flow-control settings include soft (or xonxoff), dtrdsr, and hard (or rtscts). Use a + sign before each additional setting, as shown in the following example:

  • scsi SCSI printers are rare, but if you happen to find one, you can print to its generic SCSI device, as in this example:

  • file This prints to a file. By default, CUPS disables printing to any file on the system except /dev/null. You can change this by adding a FileDevice parameter in your cupsd.conf file. Be warned that you risk very serious security breaches if you do so.

CUPS does not let you choose a backend that it knows it cannot reach. For example, if your kernel does not have parallel port support, CUPS does not list parallel ports when you run lpinfo -v. However, the system isn't perfect; a port showing up in the list does not mean that support actually exists.

Each one of these backend specifications uses its own separate backend program located in /usr/lib/cups/backend. The backend comes in at the very end of the print process.

12.5.6 PPD Files

After choosing an appropriate device, you can complete the printer definition with a PPD file. CUPS uses PPD files for its printer database.

A PPD file is in plain text and describes a printer's capabilities. CUPS keeps its default PPD files in /usr/share/cups/model; to make the options in a new PPD file available to the CUPS Web interface, put the file in /usr/share/cups/model and send your cupsd a HUP signal. When you import a PPD file into the CUPS PPD file database with lpadmin -m, CUPS makes a copy of the file in /etc/cups/ppd.

The PPD file gives you fine control over printing options. Notice that if you choose the raw interface (that is, no PPD file), you get no options with the Configure Printer button in the CUPS Web interface, so you cannot change media, duplex, banner page, and other settings.

Here is the general printer and file information from the PPD file of an Apple LaserWriter 16/600:

*FormatVersion: "4.3"
*FileVersion:   "1.1"
*LanguageVersion: English
*LanguageEncoding: ISOLatin1
*PCFileName:    "POSTSCRI.PPD"
*Manufacturer:  "Apple"
*Product:       "(LaserWriter 16/600)"

Looking elsewhere in the file, you might see some information on page sizes:

*PageSize Letter/US Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
*PageSize A4/A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"

A standard PPD file should also contain font information:

*DefaultFont: Courier
*Font AvantGarde-Book: Standard "(001.006S)" Standard ROM
*Font AvantGarde-BookOblique: Standard "(001.006S)" Standard ROM
*Font AvantGarde-Demi: Standard "(001.007S)" Standard ROM
*Font AvantGarde-DemiOblique: Standard "(001.007S)" Standard ROM
*Font Bookman-Demi: Standard "(001.004S)" Standard ROM
*Font Bookman-DemiItalic: Standard "(001.004S)" Standard ROM
*Font Bookman-Light: Standard "(001.004S)" Standard ROM
*Font Bookman-LightItalic: Standard "(001.004S)" Standard ROM
*Font Courier: Standard "(002.004S)" Standard ROM
*Font Courier-Bold: Standard "(002.004S)" Standard ROM

The preceding excerpts are from a GPL version of a PPD file. PostScript printer manufacturers provide PPD files for their products, and for the most part, these should work fine with CUPS. However, non-PostScript printers do not normally come with PPD files, so they need a third-party PPD file that specifies a print filter to rasterize PostScript. You can get CUPS PPD files at sites such as http://www.linuxprinting.org/.

12.5.7 Specifying a Filter

One of the most frequently encountered problems with CUPS is that many of the PPD files you find on the Internet contain CUPS-specific print filter parameters that you may not have on your system. You should be able to recognize these parameters and have an idea of how to correct or delete them as you go.

CUPS filters convert file formats in two ways:

  • To a common format This type of filter converts various file formats into a common format. This common format will be either PostScript or raster data. The mime.convs file controls the filters that perform the conversion. For the most part, you should not have to worry about these filters, which are covered in the next section.

  • From a common format A filter specified in the PPD file runs just before the backend to change the common format data into the language that the printer understands. If you have a PostScript printer, you probably do not need this filter in your PPD file. However, if you don't have a PostScript printer, these backend filters require a lot of attention, as you will see.

CUPS Filters and mime.convs

CUPS comes with a number of filters in /usr/lib/cups/filter that transform various intermediate file formats into printer-ready data. However, it is difficult to see where and how CUPS runs these filters.

When you print a file, you can observe something like the following in the log file (this example is for a text file):

Started filter /usr/lib/cups/filter/texttops (PID 3999) for job 25.
Started filter /usr/lib/cups/filter/pstops (PID 4000) for job 25.

To get this detailed logging, the LogLevel parameter in your cupsd.conf must be a minimum of info. However, info does not log the initial input file type; you need to set the parameter to debug in order to log this additional information.

In the log, you can see some filters running, and from the names of the filters, you know that CUPS has some sort of idea about the job's file type. Unfortunately, the actual workings of the conversion mechanism aren't terribly obvious from the log file output. Here's how the sequence works:

  1. CUPS determines the output format that the backend needs to send to the printer by looking at the PPD file.

  2. CUPS determines the input file type with the help of /etc/cups/ mime.types. In the preceding example log output, the application/ postscript rule in /etc/cups/mime.types matched.

  3. CUPS looks through the /etc/cups/mime.convs file for a suitable filter to perform the conversion between the input file format and the format that the backend needs. Consider this line from mime.convs that transforms plain-text files to PostScript output:

    text/plain                 application/postscript  33      texttops

    The four columns here are the input MIME type, the output MIME type, the estimated cost, and the name of the filter program that converts the input to the output.

  4. CUPS runs the filter or filter sequence required for the printer backend. If there are no suitable entries in mime.convs, CUPS logs this message:

    Unable to convert file 0 to printable format for job n!
  5. CUPS runs any necessary additional filter before handing the final output to the backend (see the next section).

Specifying a Backend Filter in the PPD File

Just before sending the job to the printer backend, CUPS may run a backend filter from the PPD file.

Backend filters are set with the cupsFilter parameter in the PPD file. Here is an example from the PPD file that you saw earlier:

*cupsFilter:    "application/vnd.cups-postscript 0 foomatic-rip"

As you can see, the cupsFilter parameter's value consists of three parts:

  1. An expected MIME type. In the preceding example, the type is PostScript. The default is application/vnd.cups-postscript.

  2. The relative cost of the filter (set this to 0).

  3. The filter's executable name.

The preceding cupsFilter parameter is very typical for printers that do not understand PostScript. Foomatic is a print filter that handles many different kinds of printers.

There are a few gotchas with the cupsFilter setting:

  • You don't need an extra filter if your printer already understands PostScript. Many PPD files for PostScript printers that you find on the Web contain filters that don't really do anything, but require extra software configuration. Delete any cupsFilter lines in your PPD file if your printer understands PostScript.

  • The default PPD files and mime.convs file that come with CUPS do not contain the necessary settings to rasterize PostScript files, and it can be somewhat confusing to configure the rasterizer. For example, the generic HP LaserJet PPD files in the CUPS distributions expect raster (not PostScript) input. However, the default mime.convs file doesn't contain an active entry for transforming PostScript into raster output. For this reason, you may want to avoid the standard CUPS PPD files and look on the Web for appropriate files.

  • To address the problem of rasterization, most PPD files for non-PostScript printers on the Web assume that you have Foomatic as a filter (see Section 12.5.8) with Ghostscript as the rasterization engine. If your printer doesn't understand PostScript, it's unlikely that you will be able to avoid Foomatic.

There is good news, though. Most PPD files that you find on the Web work fine if all of your software (Ghostscript, Foomatic, CUPS, and so on) is installed correctly.

12.5.8 Foomatic (for Non-PostScript Printers)

If your printer does not have native PostScript support, there may still be one more piece of the puzzle to configure — the rasterizer filter. There are several options here, but the most popular system at the moment is Foomatic.

Before going into details about Foomatic, you should be clear on the end goal here: you want a print filter to run a Ghostscript (gs) command to render PostScript input into bitmap form to send to the printer. The command arguments look something like this:

gs -q -dSAFER -dNOPAUSE -dBATCH device_options -sOutputFile=- -

This seems simple enough, but unfortunately, device_options can be a tremendous mess. There are countless combinations of printer data formats and options. Foomatic attempts to resolve these problems with a database containing options for nearly every printer model out there. You may see references to this database all over the Web but very little information on how to actually use the database.

What most documentation fails to mention is that most administrators and users don't even interact with the database. All you need to worry about is building printer configuration data, such as PPD files. In fact, this work is already done for you when you visit http://www.linuxprinting.org/ to get a PPD file for your printer. All of the information that the Foomatic filter program (foomatic-rip) needs is in that PPD file. For example, here is a portion of the HP LaserJet 1100 PPD file that contains Ghostscript arguments:

*FoomaticRIPCommandLine: "gs -q -dBATCH -dPARANOIDSAFER -dQUIET -dNOPA&&
USE -sDEVICE=ijs -sIjsServer=hpijs%A%B%C -dIjsUseOutputFD%Z -sOutputFi&&
le=- -"


See Section 12.6.3 for notes on certain HP printer drivers.

Testing Foomatic

To use Foomatic as a filter, you need the foomatic-rip program in lib/cups/filter (a symbolic link to another location works fine). You can verify that Foomatic produces the correct printer output by running foomatic-rip on the command line, generating printer output by hand. You can then send this data directly to the printer, bypassing the print spooler.

First, locate your printer's PPD file (ppd_file) and find a test PostScript file to test with (test_file.ps). Run this command to create printer data in test.prn:

foomatic-rip -v --ppd ppd_file test_file.ps > test.prn

The -v option specifies verbose operation so that you can see exactly what the filter is doing. If everything goes well, you should see the following at the end of the diagnostic messages:

KID4 exited with status 0
Renderer exit stat: 0
Renderer process finished

Closing foomatic-rip.

Successful completion also means that test.prn should now be a gigantic (probably binary) file that you can send directly to the printer device.

12.5.9 Administrative Command Overview

With the mess of print filters hopefully behind you, it's time to learn some commands for day-to-day tasks. Compared to other Unix server systems, it isn't terribly important that you know the syntax of every last command, because the Web administration interface does an adequate job in most cases (and is sometimes far preferable to the command line — for example, when doing printer media option configuration).

However, you should develop at least a passing familiarity with the following commands (remember that each command has a manual page):

  • lpadmin Adds, removes, and modifies printers.

  • lpinfo Displays device and PPD file information (for use with lpadmin).

  • lpoptions Sets printer options. To display a quick list of options for a particular printer, run this command:

    lpoptions -p printer -l
  • lpstat Displays printer and job information (after you create printers). To display a printer's job queue, use this command:

    lpstat -o printer

    To see the status of every printer on the system, use this:

    lpstat -a
  • cancel Removes a job. To remove all jobs from a queue, run this command:

    cancel -d printer -a
  • disable Disables printing (but still possibly allows new jobs on the queue).

  • enable Enables printing.

  • reject Disables print queuing.

  • accept Enables print queuing.

  • lppasswd Modifies users and passwords (for digest authentication; see Section 12.5.2).

12.5.10 Client Access Control

By default, CUPS allows printer and administration access only to localhost. If you have a network of machines that you want to grant access to your CUPS server, then you have to change your cupsd.conf file to reflect this.

To get an idea of how per-client access control works, edit your cups.conf file and search for the line that reads <Location />. It should start with a section that looks like this:

<Location />
Order Deny,Allow
Deny From All
Allow From

The Location / section defines global access-control parameters for the CUPS server. In the preceding example, the directives work together to give access to localhost ( and nothing else:

  • Order Deny,Allow Allows you to specify hosts and networks that are denied and allowed access with the Deny and Allow directives. Further more, it also means that you can override Deny directives with Allow directives. This is the most useful mode in CUPS, and you should never change it.

  • Deny From All Denies access to all clients by default. Again, you should not change this.

  • Allow From Makes an exception to the preceding Deny From All rule, granting access to localhost.

If you want to allow access for all of your printers to more clients, you can just add another rule directive after the Allow From line. The following rule directive grants access to the subnet defined by

Allow From

You may have as many Allow From client lines as you like, and you can specify the client parameter in several ways. The following five specification types are the most useful:

  • Subnet notation, as in the preceding example

  • IP addresses, such as

  • Fully qualified domain names, such as client.example.com

  • Domain wildcards, such as *.example.com

  • Network interfaces, such as @IF(eth0)

Remember that the Location / section is for global access, including printer job control and other client tasks. Administrative tasks, on the other hand, have their own Location section (<Location /admin>) that specifically excludes connections from all hosts except localhost. In fact, you have already seen this section when you forced CUPS to digest authentication. Search for it in your cupsd.conf to verify that it allows administrative access to localhost, and to nothing else.


You can specify per-printer client access by adding <Location /printers/name> access control sections, where name is the name of a printer. You'll probably need to experiment for a while to get it to work perfectly.

12.5.11 Auto-Discovery

One of the more interesting CUPS features is automatic network printer discovery. This is called browsing. Most CUPS installations have browsing active by default, meaning that CUPS listens for messages from other print servers on the network. The cupsd.conf parameter is Browsing:

Browsing On

However, without additional help, your CUPS server will likely not make itself known to the other print servers on the network. To make your CUPS server broadcast its presence, you need a BrowseAddress broadcast address parameter in cupsd.conf. For example, to send notification packets to as many hosts on the network as possible (essentially, as many as your routers allow), use this parameter:


You can think of a numeric broadcast address as a sort of inverse subnet combined with an IP address. For example, to send packets to the subnet defined by, try this:


This said, the best choice is likely the "local" interface selection that sends broadcast packets out to all network interfaces except PPP links:

BrowseAddress @LOCAL

If you have a server with several Ethernet interfaces, but do not want to broadcast on all of these interfaces, use @IF. For example, here's how to broadcast to eth1:

BrowseAddress @IF(eth1)

12.5.12 Running an LPD-Compatible Server

Browsing and broadcasting goes a long way toward allowing communication between various CUPS servers on a network, but if you want older clients running Berkeley LPD printing systems to be able to print to your CUPS server, you need to configure your server to allow jobs from these clients.

To do this, run a special LPD server frontend called cups-lpd located in /usr/lib/cups/daemon. This is an inetd service (see Section 6.3), so you want a line like this in your /etc/inetd.conf (or the xinetd equivalent):

printer stream tcp nowait cups-user /usr/lib/cups/daemon/cups-lpd cups-lpd

cups-user is your CUPS User parameter from cupsd.conf (usually lp). There is no built-in access control in cups-lpd, but like any other network service, you want to make sure that your firewall rules have adequate coverage; see Section 5.13. Remember that printer is defined in /etc/services as port 515.

12.5.13 Troubleshooting CUPS

When you have a problem with CUPS, it's particularly important to take things one step at a time. You may find this sequence helpful:

  1. Make sure that CUPS is working properly by creating a test printer with no filters (raw mode) and a device of file:/dev/null. Send a test file to the printer with the Web interface and lp, and verify that the jobs complete with lpstat:

    lpstat -W completed -o test_printer_name
    lpstat -o test_printer_name
  2. Use your printer's PPD file to activate your filter. See Sections 12.5.4 and 12.5.6 for more detail if something goes wrong. Print more test files, again making sure that the jobs finish.

  3. Add the printer's actual device, and then try another test job. If necessary, try printing to a file, then sending the file directly to the printer.

If a test print job fails and stalls, the printer state changes to "not ready," and you need to start the printer again to retry the job or run any new jobs. Do this with enable printer or the Web interface. Before you start changing files around, though, you should look at your log files, which are described in the next section.

Error Messages

The complex nature of the print spooler and filters makes it crucial that you pay careful attention to your log messages. The most important log file is /var/log/cups/error_log (the name is slightly misleading because the file also contains normal diagnostic messages).

Looking at the log reveals this format:

I [timestamp] Started filter /usr/lib/cups/filter/pstops (PID 3434) for job 26.
D [timestamp] ProcessIPPRequest: 10 status_code=0
E [timestamp] [Job 26] unable to open print file - : Permission denied

The letter at the start of the line indicates the message severity or priority. The three letters in the preceding example are as follows:

  • I An informational log message. These notices usually indicate some significant event, such as a filter invocation or job submission.

  • D A verbose debugging message. You should not care about these unless you run into a problem.

  • E An error message indicating that something doesn't work. The CUPS scheduler usually keeps running if there is an error. However, you may end up missing a feature or having a stalled printer job.

You can change the log level with the LogLevel parameter in the cupsd.conf file. The default level is info in most installations. If you want the debugging messages, you must use debug. If you change your LogLevel parameter, remember to reload your configuration file after making any changes by sending a HUP signal to cupsd.

Filter Problems

The first thing you should do after running into trouble in the print filter stage is to make sure that the CUPS filters in /etc/cups/mime.convs function properly.

To do this, first disable any filters that you might have in your printer's PPD file so that you can eliminate the backend filter from the list of things that can go wrong. You will probably only have such filters if you are using a non-PostScript printer. If that's the case, edit your printer's PPD file (the one in /etc/cups/ppd), looking for a cupsFilter parameter (see Section 12.5.7). Comment out the parameter by adding a % just after the *; for example:

*%cupsFilter:   "application/vnd.cups-postscript 0 foomatic-rip"

After making this change (and making cupsd re-read its configuration with a HUP signal), submit a test job to see if data can make it past the mime.convs filter stage to the printer device. Although you are not likely to run into any trouble with the CUPS-supplied filter programs in mime.convs, this process may help you uncover spool directory permissions problems (discussed in the next section) because these sorts of problems usually show up in the initial print filter stages.

Having worked out any kinks not involving the cupsFilter filter, re-enable this parameter and look for more trouble:

  • Verify that the cupsFilter filter is in the lib/cups/filter directory.

  • For the Foomatic filter, use foomatic-rip -v manually from the command line to check for valid output (see Section 12.5.8).

  • Check that the filter has the correct path for any necessary program.

  • If your filter relies on Ghostscript, ensure that you have the required driver by running gs -help.

Spool Directory Permission Errors

Look for this message in your error log:

E [timestamp] [Job n] unable to open print file - : Permission denied

CUPS normally runs its filters as the pseudo-user lp and the group sys, so this user must have access to the spool directory /var/spool/cups in order to access intermediate data. When fixing the permissions, look for these problems:

  • Check all component directories of /var/spool/cups. Can the lp user access each of them?

  • Make sure that you have the lp user in your /etc/passwd file.

  • Verify that lp belongs to the sys group. (Remember that you can change the pseudo-user and group with the User and Group parameters of cupsd.conf.)

Device Problems

After running through the filter gauntlet, you are ready to send output to devices. Fortunately, there is relatively little that can go wrong at this final stage:

  • The lp user must have write access to any printer device directly connected to the system. In addition, check the kernel bootup messages and /proc to ensure that the kernel recognizes the device ports.

  • For network printers, make sure that your host can reach the printer. If your device is the socket type on TCP port 9100, test the connection with this command:

    telnet printer_address 9100

    Terminate a successful connection by pressing CONTROL-], then CONTROL-D. Unless you know the printer's native language, this connection does little good other than confirming that it can be made.