1

I'm setting up CUPS of one server to have the same set of printers as another CUPS server. I generally live in the CLI and it's a long list of printers, so I was wondering how simple this could be made. Looking through the commands' docs, I see that I can add printers like this:

lpadmin -p $printer_name -E -v $printer_location -m $printer_model

I can get the $printer_names and $printer_locations with:

lpstat -v

but I can't seem to find a command that will tell me the $printer_model of each printer. I'm tempted to just hack it by scraping http://localhost:631 with curl to get the human-readable models then matching with lpinfo -m to get something suitable for lpadmin -m, but I hope there's something more conventional.

2 Answers 2

1

You might be able to grep something from the ppd files in /etc/cups/ppd/ and the (protected) file /etc/cups/printers.conf, but there is a Python interface pycups to the cups library which can talk to the server for information. For example,

#!/usr/bin/python3
import cups
conn = cups.Connection()
printers = conn.getPrinters()
for printer in printers:
    p = printers[printer]
    print(printer, p['printer-make-and-model'])

The returned printer dict has entries: printer-make-and-model printer-is-shared printer-type device-uri printer-location printer-uri-supported printer-state-message printer-info printer-state-reasons printer-state. I found pycups in the rpm package python3-cups.

4
  • These are good suggestions. Unfortunately, with both I'd still need to match with lpinfo -m to get the string that's required for lpadmin -m. The ppd files in /etc/cups/ppd/ sometimes have bits of info under different keys that can help skip matching with lpinfo -m, but not all the info all the time. And even matching with lpinfo -m is not a complete solution because model names can change even though the ppd path/uri/whatever stays the same. Maybe I should make a blogpost on how surprisingly complicated this is.
    – JoL
    Commented Jul 31, 2021 at 19:09
  • Simplest solution so far (using your second suggestion but with ruby's cupsffi gem): join -t@ -j2 -o 1.1,2.1 <(ruby -r cupsffi -e 'CupsPrinter.get_all_printer_attrs.each {|n, a| puts "#{n}@#{a["printer-make-and-model"]}"}' | sort -t@ -k2) <(lpinfo -m | sed 's/ /@/' | sort -t@ -k2) | column -ts@. This can miss cases where the human-readable model name changed because of a driver update, etc. hpcups includes the package version in the model names, for instance.
    – JoL
    Commented Jul 31, 2021 at 19:09
  • I wonder if copying /etc/cups/ppd/ between machines suffices for setting the printers up.
    – JoL
    Commented Jul 31, 2021 at 19:11
  • I'm sure you would need /etc/cups/printers.conf too, and possibly /etc/printcap, though it can regenerate that. You should probably move your ruby solution into a answer so others can benefit from it, and it will be more readable.
    – meuh
    Commented Jul 31, 2021 at 19:14
1

There's no conventional command for getting the driver of an installed printer.

Here's a solution for listing lpadmin -m acceptable ppd specs (relative paths,drv:/// and/or gutenprint*:// URI's) based on meuh's suggestion to use a library:

# hpcups and gutenprint put their version in the model names. That means
# that if you install a printer then update the drivers, the model of the
# printer won't match with those available listed by `lpinfo -m`. So, we'll
# strip the version.
strip_versions() {
  sed -E 's/(, hpcups|- CUPS\+Gutenprint).*//'
}

# Using @ as a custom field delimiter since model names have whitespace.
# `join` is to match the printers' model names with those of the available
# drivers.
join -t@ -j2 -o 1.1,2.1 \
  <(
    ruby -r cupsffi -e '
      CupsPrinter.get_all_printer_attrs.each do |name, attrs|
        puts "#{name}@#{attrs["printer-make-and-model"]}"
      end
    ' | strip_versions | sort -t@ -k2
  ) \
  <(lpinfo -m | sed 's/ /@/' | strip_versions | sort -t@ -k2) |
# We may get multiple ppd specs per printer. For a few printers, I'm
# getting a relative path from the system model directory and either a
# drv:/// uri or a gutenprint.5.3:// URI. We'll filter out all but the
# first per printer.
awk -F@ '!a[$1]++' |
# Change the @ column delimiter for whitespace and align columns.
column -ts@ 

cupsffi is a ruby gem that can be installed with gem install cupsffi.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .