Translation(s): none


Techniques to deal with printing problems on the CUPS based printing system.

Introduction

The aim in this page and the sections of the wiki linked from it is to give some insight on printing with CUPS in Debian 8 (Jessie) and Debian 9 (Stretch). There are differences between the two distributions but the filtering systems are identical in principle and nearly so in practice. It is hoped that there will be sufficient detail to give an understanding of how parts of CUPS and the filtering system work and co-operate and to enable effective troubleshooting.

CUPS (a product of Apple Inc.) is the manager of all printing processes via its scheduler, cupsd. It also provides a number of filters which prepare a print job for sending to a printer. However, some filters essential for Linux systems were not required by Apple and were donated to the Linux Foundation and now form the basis for the cups-filters and cups-filters-core-drivers packages in Debian. When we take the contributions of developers of other free software such as Ghostscript, Poppler, Gutenprint and Avahi into account we can glimpse the complexity of the relationships between the components of the printing system. In spite of this complexity the debugging methods described later can be very effective if used in a organised way.

Throughout this account CUPS is used to refer to what you get if the source is downloaded from cups.org and compiled. cups-filters is a Linux Foundation project which interworks with CUPS but responsibility for its maintenance lies with the Linux Foundation and openprinting, not CUPS.

The PDF-centric Workflow

Prior to Wheezy the filtering system was devised to process PostScript files; that is, any file recognised by CUPS as a known MIME media type was first converted to PostScript before being processed. At present we have a system which is designed to process files in PDF format; known MIME media types are first converted to a PDF if necessary.

An ideal chain of filtering would be

PDF in -> pdftopdf -> PDF out -> Printer which interprets PDF

PDF in is relatively easy to accomplish; we simply get applications to generate and send PDF, which is what Firefox/Iceweasel and Evince (amongst other applications) do by default. But not all applications do generate PDF and users still want to print text and PostScript files. Also, the printer may not understand PDF but require PostScript, PCL or some proprietary language. A generalised filtering chain would be

File in -> convert to PDF -> pdftopdf -> PDF out -> Convert to something the printer understands -> Printer

Note the initial conversion to PDF and the presence of the pdftopdf filter. This is a PDF-centric workflow.

There is one important situation (prior to CUPS 2.1.0 and cups-filters 1.10.0) in which cups-filters departs from the PDF workflow. That is when the input file is PostScript and the file is being sent to a PostScript printer. We should have

Postscript in -> pstopdf -> pdftopdf -> pdftops -> PostScript printer

but. although this generally works, it can introduce buggy behaviour such as delays and font problems because of the pstopdf and pdftops conversions. After a discussion the filter chain for PostScript job sent to a queue which feeds a printer which can interpret PostScript was altered and now uses pstops:

Postscript in -> pstops -> PostScript printer

pstops is a CUPS filter and is part of the older PostScript-centric workflow. A second situation where the PDF printing workflow is departed from occurs for PostScript from the Adobe Reader. Details are in /usr/share/cups/mime/cupsfilters.convs.

Since CUPS 2.1.0 the PPD files of the local print queues in /etc/cups/ppd/ are not world-readable as the default permissions of the ConfigFilePerm option in /etc/cups/cups-files are applied. A consequence is that the pstopdf shell script cannot read the PPD file of a print queue directly from the /etc/cups/ppd/ directory, so cups-filters 1.10.0 integrated the functionality of pstopdf into the gstoraster filter with the wrapper filter gstopdf. Post-1.10.0 the filter chain has become

  • PostScript in -> gstopdf -> pdftopdf -> PDF out -> Convert to something the printer understands -> Printer

The CUPS Error Log

For debugging the primary tool is the error log, /var/log/cups/error_log. Diagnosing printing problems is not always easy but without the error log it can make progress to a solution difficult. Don't forget that not everything which is in the error_log is the responsibilty of CUPS. Errors in the filtering chain are also logged there and could be the responsibilty of other programs such as cups-filters, Ghostscript, Poppler, colord etc, all non-CUPS software. In essence, CUPS has the task of spooling and scheduling print jobs and uses the error_log to make a record of this.

Also bear in mind the error_log may shed little light on some problems and other techniques and approaches may need to be employed. There could be misconfigurations in CUPS' files, the printer or a PPD file; the input file from an application might be defective in some way; the filter chain might be suboptimal for the job.

To enable debug logging (which is sufficient for most purposes):

cupsctl --debug-logging

For all the gory detail:

cupsctl LogLevel=debug2

To turn off debug logging and return to LogLevel=warn:

cupsctl --no-debug-logging

cupsd will be restarted automatically after using any of these commands.

The file /etc/cups/cupsd.conf can also be edited by replacing LogLevel warn with LogLevel debug or (for masochists) LogLevel debug2. cupsd will need a manual restart if this is done:

systemctl restart cups

For reasons we will not go into here the error_log could have many lines saying cupsd is not idle any more, canceling shutdown. If you find them distracting the following command will remove them:

grep -v "not idle any more" /var/log/cups/error_log | less

It is not possible to give a complete account of what to look for in an error_log because the job and the setup in the CUPS configuration files cupsd.conf and cups-files will affect its contents. The presence of error and failed should ring alarm bells but tracking down the cause may not be as easy as one would like. Handy search terms are Auto-typing and filter. Both outcomes should conform with your expectations of how a job should be processed. A glance at argv[5] is always worth it to see what options are being sent to CUPS.

The error_log may be emptied by root with

>/var/log/cups/error_log

Capturing the File Received by CUPS

A file submitted for printing by an application or by lp/lpr first enters /var/spool/cups. If a print queue is disabled with

cupsdisable <print_queue>

it stays there and does not enter the filtering subsystem. Such a file can be identified from its date-stamp and because its name will begin with a d. The file type can identified with the file utility and should be capable of being viewed to see what the application has sent. It can also be processed with cupsfilter to emulate the expected filtering process and examine what happens at each stage.

Re-enabling the print queue gets the file printed:

cupsenable <print_queue>

If you prefer to clear out /var/spool/cups there is

cancel -a -x

Capturing the File Sent to the Printer

Any print job can be printed to a file. As root, have FileDevice Yes in /etc/cups/cups-files.conf. Set up a print queue which prints to a file rather than sending to a printer. Either

lpadmin -p <print_queue> -v file:/tmp -E -m (or -P) <PPD_file>

or use the web interface.

What can be done with this printer-ready file? One possibility is that it might be capable of being viewed. If it looks fine the reason for a bad result on paper could lie with the backend used to send it to the printer or the way the printer interprets the file.

If the file cannot be viewed you could examine the previous stages which lead to its production and see whether they give acceptable outputs. If they do, you might begin to think in terms of three causes for the problem:

Backends and the Device URI of a Print Queue

Once the filtering system has produced a printer-ready file it is sent to the printer by a backend driver, which is really just another filter. The backend driver chosen is determined by the device-uri used when the print queue was deployed. For example,

  lpadmin -p <print_queue> -v socket://<IP or hostname> -E -m <PPD_file>

would use the socket backend.

The command

  /usr/sbin/lpinfo -v

lists backend devices and is very useful for discovering if a printer or printer device is detected by CUPS.

Testing a Backend and a Printer

Suppose you have a printer-ready file produced via the filtering system using cupsfilter or which has been captured before being sent to the printer. The command

   lp -d <print_queue> -o raw <printer-ready_file>

will avoid the filtering system entirely and use only a backend filter before the file is passed to the printer. A record of the transaction will be in the error_log. If there is a problem with the job being printed you can deduce it lies with either the backend (usb, socket, ipp etc) or the printer. To rule out the backend as a cause of a problem the printer-ready file can be sent directly to the printer.

For a printer connected to a parallel port:

cat <printer-ready_file> > /dev/lp0

For a USB connected printer

cat <printer-ready_file> > /dev/usb/lp0

It would be as well to check these are the correct usable devices on your system.

Network connected printers require a network-aware application such as netcat to process a file:

  nc <printer_IP_or_host_name> <port> < <printer-ready_file>

<port> can be 9100, 9101, 9102 etc for a socket connection (JetDirect), 631 for the IPP protocol and 515 with the LPD protocol.

Problems Printing to a PostScript Printer

It can sometimes happen that a file sent to a PostScript printer fails in some way. For example, an error message might be produced on the first page and subsequent pages are blank. The cause is thought to lie with buggy behaviour in the printer's PostScript interpreter even when given valid PostScript.

The filtering chain might be

  PDF file -> pdftopdf -> pdftops -> PostScript -> printer

The pdftops filter has the option to convert the PDF into PostScript using Ghostscript, Poppler, Cairo, Adobe Reader or Mupdf. The default mode is one which uses Poppler when the printer make is Brother, Minolta or Konica Minolta but Ghostscript for other printer models. If there is a problem with one of these other models it may be beneficial to switch to rendering PostScript from the PDF with the pdftops-renderer option. Details are in /usr/share/doc/cups-filters/README.txt.gz. See also POSTSCRIPT PRINTING DEBUG MODE in the same document. To use Cairo as the renderer:

lpadmin -p <print_queue> -o pdftops-renderer-default=pdftocairo   (For an existing queue).
lp o pdftops-renderer=pdftocairo <print_job>  (On a job-to-job basis).

Problems Printing to a USB Connected Printer

A USB problem can be difficult to track down. The USB backend uses libusb and there is the possibility of a bug in that software. USB to parallel adapters do not always give trouble-free operation. Also, it is not entirely unknown for printers to have bugs in their implementation of the USB standard and, indeed, CUPS has quirks rules to deal with such issues. Options to handle some USB problems have been added to CUPS. Here is an account and analysis of a printing problem solved by the application of a USB quirk.

lpadmin -p <print_queue> -v <deviceuri> -o usb-unidir-default=true -E -m <PPD_file>   (For a new queue).
lpadmin -p <print_queue> -o usb-unidir-default=true   (For an existing queue).
lpadmin -p <print_queue> -R usb-unidir-default        (Remove default).

lpadmin -p <print_queue> -v <device-uri> -o usb-no-reattach-default=true -E -m <PPD_file>   (For a new queue).
lpadmin -p <print_queue> -o usb-no-reattach-default=true   (For an existing queue).
lpadmin -p <print_queue> -R usb-no-reattach-default        (Remove default).

Problems Printing to a Network Connected Printer

+---------+    Ethernet cable    +---------+     +--------+
|         |<-------------------->|         |<--->|        |
| Printer |                      | Network |     | Server |
|         |<====================>|         |<===>|        |
+---------+      Wireless        +---------+     +--------+

/usr/lib/cups/backend/snmp

ping <IP address>

nmap <IP address>

The following netcat command tests whether the printer can be reached on port 631:

nc -z <IP_address_or_hostname> 631 && echo ok || echo failed

If the printer cannot be reached it is switched off or has no service on port 631 or there is some basic network problem

avahi-browsed -art | less

address =, port = and rp= give its IP address, the services it offers and the resource part of an IPP device-uri. If you have a printer which is capable of driverless printing

driverless

will give you the hostname and IPP device-uri for the printer.

Problems Printing with the IPP Backend

In CUPS 1.5.x the IPP backend was rewritten to make it conform more rigorously to IPP standards. Unfortunately, it is not unknown for IPP implementations on some printers and print servers to be buggy and the change resulted in some of them failing to print. As these problems are caused by bugs in the IPP implementations of the hardware and completely IPP-conforming hardware works correctly with the IPP backend of CUPS 1.5.x they were not considered as bugs in CUPS and so not fixed or worked around by CUPS upstream.

A solution is to revert to using the less stringent IPP backend from CUPS 1.4.x for the network device-uri of a print queue. It is provided as ipp14 and offered as an option with lpadmin, the CUPS web interface and system-config-printer.

lpadmin -p <print_queue> -v ipp14://<IP or hostname> -E  -m <PPD_file>

Problems with mdns/DNS-SD

Discovery of mDNS (Bonjour) shared printers takes place by default when avahi-daemon is installed. Applications using the GTK dialog subsystem will see these printers in their dialogs. Adding cups-browsed to the system allows other applications and the command line programs also to know about these Bonjour advertised print queues and printers.

Browsing for mdns/DNS-SD services can be done with avahi-browse or its GUI equivalent, avahi-discover.

avahi-browse -art

It is possible for all the queue filters to operate correctly and for the backend to behave impeccably but nothing gets printed. One cause is a firewall misconfiguration. Check with

iptables --table filter --list | grep mdns

and look at the avahi-browse -art output. Failed to resolve service and an address line which is not in the form xxx.xxx.xxx.xxx would be indications of such a misconfiguration.

A failure to get the print job to a remote printer might also be a router problem or bugs in avahi-daemon. The first could necessitate powering the router off and on; resolving the second is beyond the scope of this wiki page.

Reporting Bugs

The Debian printing system based on CUPS has matured over the years and generally operates reliably with a great number of printers. However, in what is still a developing environment, bugs are to be expected and some of them may visibly affect the printing process. With the large number of packages involved in the printing system it can be perplexing to decide which one a bug applies to. If the report is sent to the cups package there is no harm done.

A user's reaction to an inability to print can vary from viewing it as merely annoying up to intolerable. In spite of the inconvenience it is rarely the case that a failure to produce a satisfactory printout deserves setting the severity level on a bug report to anything greater than important, which is described as

a bug which has a major effect on the usability of a package, without rendering it completely unusable to everyone.

The usual program employed to report a bug is reportbug, which will guide you through the process. In addition to describing your problem there are other data which are useful to give a complete picture of your issue. The printer vendor and model and how it is connected (USB, parallel, network etc) to the machine are often relevant details. Try

   /usr/sbin/lpinfo -l -v

for the make and model. Very useful detail can also be obtained from an error_log showing what happens when printing takes place. Compressing a lengthy log with gzip or xz is an option to consider taking. If cups-browsed is the subject of the report, consider activating debug logging for it and attaching the log and your cups-browsed.conf file to the mail.

See Also