Skip to content
FreeBSDDeep Dive Published Updated 10 min readViews unavailable

FreeBSD Legacy LPD Print Queues: Maintain Existing Services and Migrate

Maintain legacy FreeBSD LPD queues safely, understand the suite's deprecation, verify spool behavior, and plan migration before removal.

FreeBSD 15.1 still includes the Berkeley line printer suite, but the official release notes mark it deprecated and say it is scheduled for removal before FreeBSD 16.0. The notes advise users to evaluate alternatives such as print/cups or sysutils/LPRng from the Ports Collection. Treat the commands here as a maintenance and migration guide for an existing installation, not a recommendation to build a new service around LPD. Confirm the status on the exact target release before planning a change.

The legacy spooler accepts jobs, holds them while a printer is unavailable, and submits them according to a queue definition. That does not make every USB or network printer usable: the device must understand the data language being sent, and the connection path must match the configured backend.

Existing LPD queues are most manageable when the input is basic text or a carefully defined legacy workflow. A PostScript file sent to an ASCII-only printer will not become printable merely because lpr returns success. Likewise, a USB device node appearing in devfs proves hardware discovery, not that the printer can interpret the job. This guide treats queue state, data format, transport, and printer status as separate diagnostic layers.

Confirm the device and language first

Before creating a queue, identify the printer connection and its supported page-description languages from the vendor’s documentation or a known-good host:

usbconfig
dmesg | grep -i -E 'ulpt|unlpt|lpt|printer'
ls -l /dev/unlpt* /dev/lpt*

Not every device uses a parallel or USB printer driver, and not every USB printer accepts raw text. Network printers may expose several services with different protocols and security policies. Do not infer support for LPD simply because a printer has an Ethernet port or advertises a vendor-specific discovery service.

Select the input format before selecting a filter. Plain ASCII text is directly printable only if the device supports it. PostScript, PCL, and host-based printer protocols have different requirements. A printer that accepts PostScript can consume that language directly; one that accepts only PCL may require a documented converter; a host-based model may depend on proprietary software from a third party. Do not stream PDF or arbitrary binary data to a printer as a “test.”

For a first test, use a short harmless ASCII message. It should contain plain printable text and line breaks, not confidential material or a large multi-page file. If the output is garbled, clipped, or staircase-formatted, troubleshoot language, page width, newline handling, and text filters before changing queue scheduling.

Define a local printcap queue

The FreeBSD Handbook’s quick-start configuration creates a spool directory and an entry in /etc/printcap. Adapt the device path and queue name to the actual host:

install -d -o daemon -g daemon -m 0770 /var/spool/lpd/lp

lp:+        :lp=/dev/unlpt0:+        :sh:+        :mx#0:+        :sd=/var/spool/lpd/lp:+        :lf=/var/log/lpd-errs:

The lp entry names the queue, lp points to the local printer device, sh suppresses a banner page, mx#0 removes the queue’s file-size limit, sd identifies the spool directory, and lf names its error log. These settings are examples from the Handbook pattern; review the local printcap(5) manual for the syntax and supported capabilities on the target release. Avoid copying a device node or unrestricted spool policy without checking the printer and the environment.

If the printer is directly connected to a network and explicitly supports the LPD protocol, printcap can describe a remote host and remote queue instead of a local device. The remote printer must actually offer a compatible LPD queue. Do not substitute a raw TCP port or a web administration endpoint for the remote LPD protocol. Confirm the host name, queue name, transport, and data language with the printer administrator.

Enable the included LPD service using the documented rc variable and start it:

sysrc lpd_enable="YES"
service lpd start
service lpd status

On a dedicated print client that submits only to another server, running a local LPD listener may not be needed. Use the configuration appropriate to the role and the installed release. Keep service exposure within the intended print network, and do not make a legacy spooler reachable from untrusted networks.

Validate the selected queue and submit one test job:

lpc status lp
printf "FreeBSD LPD test\nSecond line\n" | lpr -P lp
lpq -P lp

Use the local queue name consistently. lpr submits a job, lpq reports queue state, and lpc controls the spooler. A successful submission means the local spool accepted the job; it is not proof that the printer produced a page. Keep the job identifier and compare it with printer-side status.

Inspect queues before cancelling or retrying

When a job is delayed, inspect the queue and daemon messages before removing anything:

lpq -P lp
lpc status lp
tail -100 /var/log/lpd-errs
tail -100 /var/log/messages

The exact log destinations depend on the printcap error log and syslog configuration. A queue may be disabled, stopped, active, or waiting for a device. Determine which state is present before using an lpc command. A job blocked on an offline printer differs from one that the printer accepted but rendered incorrectly.

Use lpc enable and start only after the cause of a disabled or stopped queue is understood:

lpc enable lp
lpc start lp
lpc status lp

Disabling a queue prevents new jobs from being accepted; stopping it affects processing. The exact effect and syntax of lpc subcommands are documented by lpc(8). Do not run a broad command against all queues when only one queue is under maintenance. If multiple queues share a printer or spool directory, map those relationships first.

Cancel a specific job by its identifier only after confirming it is the intended job:

lpq -P lp
lprm -P lp 123

Replace 123 with the actual job number reported for the selected queue. Queue identifiers may be reused, and deleting a job is irreversible from the spooler. Preserve job owner, submission time, size, and error context when investigating a stuck or duplicate print. For sensitive documents, follow the organization’s retention and printer disposal policy.

Do not edit or delete spool files manually to clear a queue. The daemon maintains metadata and lock state that can be corrupted by ad hoc removal. Use the documented queue controls, and keep a copy of any configuration file before making changes. If the queue is damaged, stop it according to the manual and repair it using the supported administrative procedure.

Diagnose each delivery boundary

The lpr command cannot submit. Verify the queue name, printcap syntax, spool directory ownership and mode, daemon enablement, and local error log. Check that the caller has permission to submit and that the spool filesystem has available capacity. Fix a full or unwritable spool before retrying many jobs.

The job remains queued. Determine whether lpd is running, the queue is enabled, the device node exists, the remote server resolves, and the printer is ready. Check the daemon’s log and the printer’s own status. A network connection test can show reachability but does not prove that LPD is listening or that the queue name is valid.

The job leaves the queue but no page appears. Confirm printer-side job history, connection, consumables, and media state. Verify that the printer recognized the submitted language. Some devices silently discard unknown data or require a vendor converter. Do not infer physical output from spooler job removal.

Text prints with staircase line endings. The printer may not perform the expected carriage return when it receives a line feed. The Handbook documents output filters for this class of behavior. Use a filter that is explicitly appropriate for the printer rather than editing the source file or inserting arbitrary control bytes.

Pages are garbled or incomplete. Compare a small ASCII test with a known supported PDL, inspect filters and queue capabilities, and ensure that a binary job was not transformed as text. If a converter is involved, identify its package version and exact options. A filter that works for one printer model may produce invalid data for another.

Keep spool capacity and service behavior predictable

The spool directory is persistent operational state. Place it on a filesystem with enough room for expected job sizes and define monitoring for free capacity. The example mx#0 removes a per-job size limit; in a multi-user environment this can permit very large jobs to consume storage. Use a limit appropriate to the workflow, and test its behavior with the installed lpd implementation.

Define retention for failed jobs and logs. A stale queue can contain confidential content and can also block later jobs. Review who can inspect spool files and who is permitted to remove jobs. Do not treat print spool data as disposable merely because it is temporary. Retain only what the business policy requires and remove it through the spooler.

LPD does not automatically provide document conversion, printer-driver selection, a modern color-management pipeline, or an enterprise print-management database. For a mixed fleet of modern printers, consult the vendor and evaluate a maintained print system from ports. The presence of lpd in the base system is not a statement that it is the right service for every printer.

Migrate before the base utility disappears

Inventory every queue, local or remote printer, printcap capability, filter, user, job-size policy, spool path, and application that submits work. Identify the input document formats and any conversion package. A replacement system may use a different queue model, printer discovery mechanism, authentication boundary, and language-conversion chain; recreating only the queue name can silently change output behavior.

Build the replacement on a staging host or an isolated queue. Send representative ASCII and non-ASCII documents, verify page size, orientation, duplex, fonts, and filters, and check how large or failed jobs are retained. For network printers, confirm the target protocol and server-side policy. Do not assume that a legacy raw queue maps directly to a modern print service.

Choose a cutover window, stop new submissions to LPD, drain or explicitly cancel the old queue, and compare the final job inventory with the migration record. Preserve the previous printcap file, filter configuration, and spool evidence until the new service has passed acceptance. Remove obsolete startup configuration only after confirming no application still submits to the old queue and the replacement can recover after reboot.

The release-note alternatives are examples, not a universal product endorsement. Review current port maintenance, printer compatibility, and the deployment’s operating requirements before selecting one. The important acceptance condition is an actively supported queue service on the target FreeBSD release with verified end-to-end output.

Where the target release has already removed the base suite, do not copy an old printcap file and assume the same service commands or spool format exist. Move queue definitions into the selected replacement’s configuration and test it on that release. The old manuals remain useful for understanding existing job behavior and preserving a migration inventory, but they are not evidence that a removed command can be invoked on a newer base system.

Operational acceptance

An accepted queue has a documented queue name, input language, connection type, device or remote host, spool path, ownership, size policy, and service role. Submit a harmless sample, observe it in lpq, confirm it exits the queue for the expected reason, and verify the physical page or a trustworthy printer-side receipt. Test the recovery path for a paused queue and removal of one known test job.

Record the FreeBSD release, printer model and firmware, driver/device node, printcap entry, filter chain, spool filesystem, job ID, logs, and observed page result. Separate spool acceptance from physical output in monitoring. A queue is production-ready only when every stage, from user submission to correct printed content, has been proven and the failure path is observable.

For an LPD maintenance change, include the deprecation status and migration owner in the change record. A successful test on an older release does not establish that lpr utilities will remain available after an OS upgrade. Keep the planned replacement and test date explicit so a deprecated queue does not become an unplanned outage during the next major-version transition.

Related:

Sources:

Comments