Notes / cupsprintersmdnsavahinss-mdnsarch
CUPS "Unable to locate printer *.local" even though avahi-resolve finds the printer
CUPS jobs to an ipp://printer.local queue never printed and lpstat showed "Unable to locate printer". Avahi could see the printer, but /etc/nsswitch.conf had no mdns entry, so normal name lookups for .local failed. Adding mdns4_minimal [NOTFOUND=return] to the hosts line fixed it.
Symptoms #
A network printer had been set up in CUPS using its mDNS hostname. The queue accepted jobs,
but nothing printed and jobs piled up. lpstat -t showed:
textdevice for Office_Printer: ipp://printer.local:631/ipp/print
Unable to locate printer "printer.local".
At the same time, Avahi had no trouble finding the printer:
bashavahi-resolve -n printer.local # returns the printer's address
But ordinary name resolution did not:
bashgetent hosts printer.local # prints nothing
ping printer.local # Name or service not known
Root cause #
CUPS resolves the queue's hostname through the normal glibc resolver (NSS), not by asking
Avahi directly. Whether NSS knows about .local names is decided by the hosts: line in
/etc/nsswitch.conf, which here was:
texthosts: files dns myhostname
There is no mdns module in that list, so .local lookups went to files and dns, both
of which fail. The nss-mdns package (which provides the mdns* NSS modules) was already installed; it
just was not enabled in nsswitch.conf. On Arch it is only an optional dependency of
avahi, so on another machine you may need pacman -S nss-mdns first.
The difference between avahi-resolve (works) and getent hosts (fails) is the tell:
avahi-resolve talks to avahi-daemon directly, getent goes through NSS the way CUPS does.
Fix #
Add mdns4_minimal [NOTFOUND=return] to the hosts: line, before dns:
bashsudo sed -i.bak 's|^hosts:.*|hosts: files mdns4_minimal [NOTFOUND=return] dns myhostname|' /etc/nsswitch.conf
If your hosts: line has other entries (for example resolve or mymachines), edit it by
hand instead of replacing the whole line; the point is to insert
mdns4_minimal [NOTFOUND=return] before dns.
Check:
bashgetent hosts printer.local # now prints the printer's address
No service restart is needed: NSS reads nsswitch.conf on each lookup, and CUPS picked up
the change on the next job.
[NOTFOUND=return] stops the lookup when mDNS says a .local name does not exist, instead
of falling through to DNS. That avoids slow upstream DNS queries for names that will never
resolve there.
The same fix applies to any .local device on the machine (AirPlay receivers, other
Bonjour/mDNS hosts), not only printers.
Do not cancel the stuck jobs #
Jobs stuck on a name-resolution failure are real prints. Once the hostname resolves, CUPS
retries them and they print. If you cancel them while diagnosing (cancel -a), they have
to be printed again. We made this mistake once; leave the queue alone and let it flush.
How it was found #
bashlpstat -t # queues and the last error per queue
avahi-resolve -n printer.local # what Avahi sees
getent hosts printer.local # what NSS (and CUPS) sees: the gap
avahi-browse -art # list mDNS services on the network
grep ^hosts /etc/nsswitch.conf # look for mdns4_minimal
pacman -Q nss-mdns # confirm the NSS module is installed
References #
- Arch Wiki, Avahi: Hostname resolution.