Errors from whatis command. Unable to rebuild database with makewhatis

catalinafishmanterminal

How can I update the whatis database?

$ sudo /usr/libexec/makewhatis
Password:
makewhatis: /usr/share/man/whatis.tmp: Read-only file system

I believe being able to update this database will solve some other issue I'm having. My path to discovery as follows…

I recently started noticing that fish shell completions were annoyingly slow on my machine, possibly shortly after upgrading to Catalina.

I did a little profiling with fish -d5 and noticed that the majority of the time was spent on the apropos command. I did some reading and learned that the tools apropos, whatis and makewhatis are all related. They index man pages and make them searchable. Fish shell is (correctly) using them to offer helpful completions.

When I run whatis or apropos standalone, I get the following output:

$ whatis man
hugo-gen-man(1)          - Generate man pages for the Hugo CLI
groff_man(7)             - groff `man' macros to support generation of man pages
groffer(1)               - display groff files and man~pages on X and tty
man(1)                   - format and display the on-line manual pages
man.conf(5)              - configuration data for man
zshall(1)                - the Z shell meta-man page
xml2man(1)               - MPGL to mdoc (man page) translator
makewhatis: /usr/lib/./libgutenprint.2.dylib: No such file or directory
makewhatis: /usr/lib/libsasl2.2.0.1.dylib: Not a directory
makewhatis: /usr/lib/libldap.dylib: Not a directory
makewhatis: /usr/lib/libsqlite3.0.dylib: Not a directory
makewhatis: /usr/lib/libcom_err.dylib: Not a directory
...

Followed by at least 100 more lines of the "Not a directory" messages. I believe it is all these useless lines that are slowing things down.

So I thought maybe I just need to rebuild the whatis database (perhaps after the Catalina upgrade?). However, it doesn't seem to work:

$ sudo /usr/libexec/makewhatis
Password:
makewhatis: /usr/share/man/whatis.tmp: Read-only file system

So this part is a little disturbing. How can I rebuild the whatis database? I have a hunch this will solve my issues if I can figure it out.

Best Answer

The following can be used as a workaround for the macOS 10.15.1 version of the apropos command, wherein it spews out complaints of the form makewhatis: /usr/lib/lib … .dylib: Not a directory.

First create the workaround script:

$ mkdir -p ~/workarounds
$ sed -e 66s@/usr/lib@@ /usr/bin/apropos > ~/workarounds/apropos.macos_10.15.1 
$ diff /usr/bin/apropos ~/workarounds/apropos.macos_10.15.1 
66c66
<     for d in /var/cache/man $manpath /usr/lib
---
>     for d in /var/cache/man $manpath 
$ chmod +x ~/workarounds/apropos.macos_10.15.1

Next add an alias to your shell to tell it to use the workaround script, until a newer version of the canonical script becomes available.

For Zsh you can use the following command:

$ /bin/cat <<END >> ~/.zshrc
# Workaround for broken apropos command.
alias apropos=~/workarounds/apropos.macos_10.15.1
END

For other shells such as ksh or bash, use ~/.profile or ~/.bash_profile, as appropriate.

What does the workaround do?

Apropos requests (and man -k requests) are handled by the /usr/bin/apropos script. That script searches for “whatis” database files in all the directories of the man path (see man —path), plus /var/cache/man and /usr/lib. The checks for /var/cache/man/whatis and /usr/lib/whatis appear to be there for historical reasons, however those files are not actively generated in Mojave or Catalina. A lot of different people have contributed to the various flavours of Unix over the years, and many of them had different good ideas about where to put different types of files. At some point in time, somebody decided that /usr/lib would be a good place to put a whatis file, and at some other point somebody else figured that /var/cache/man would be a good place. Others thought that the appropriate place would be the respective man page directories. Different solutions that seemed appropriate at the time. The apropos script has traditionally checked those locations in case a whatis file was present.

With the move to making the system directories on Catalina read-only (a good move), whatis database files can not be written to directories such as /usr/share/man. There are different ways that Apple could handle that, but for this release somebody decided to alter the apropos script by making it generate results on the fly by calling /usr/libexec/makewhatis.local for any man page directory that does not contain a whatis file.

That new apropos code works fine for actual man page directories, and for /var/cache/man (since it doesn’t exist), but it fails for /usr/lib. The workaround detailed above just eliminates /usr/lib from the list of directories searched.

As a final step, set yourself a reminder for a month or two from now to check whether Apple has fixed the apropos script. If so remove your workarounds, by removing the alias and the workaround script.