6

I'm trying to use the command /usr/bin/man -H 3 free to open the manpage in my browser, but each time I run the command, the browser opens a non-existing file and of course the page cannot be displayed.

What am I doing wrong?

My man command is supplied by man-db

1 Answer 1

9

At least on my system (Arch Linux, man-db 2.9.4, Firefox 88.0), man creates a temporary directory in /tmp/, writes the generated HTML file in it, invokes the browser with the HTML file as an argument and, when the browser process exits, removes the temporary directory (to clean things up, I guess).

While this creates no issue with some browsers (e.g. Lynx), a race condition may occur with others (Firefox, in my case; I also briefly tested Chromium, getting similar results). As far as I can see, the HTML file is correctly opened if man opens a new browser window. On the other hand, if the man page is opened as a new tab in an existing browser window, the browser process started by man returns early and the file is already gone when a different browser process tries to read it.

I see no man option aimed at preventing the temporary HTML file from being deleted. But, noting that the argument to the -H/--html option (or, equivalently, the value of the BROWSER environment variable) can be a shell command, a quick workaround may be:

BROWSER='firefox %s; sleep 5' man -H 3 free

(sleep gives Firefox time to load the page before the file is deleted; of course, it will be impossible to reload it).

Or, if you are willing to implement your own mechanism for deleting the temporary HTML files:

BROWSER='cp %s /path/to/file.html; firefox /path/to/file.html' man -H 3 free

(This ignores other assets that may be generated alongside the main .html file, which may therefore be rendered incorrectly).

Or, if you are fine with keeping the temporary directories (e.g. you do not generate lots of them, your /tmp is volatile and your system is rebooted regularly enough):

BROWSER='firefox %s && false' man -H 3 free

(The temporary directory is not deleted when the browser command returns an error to man; as a drawback, an error message is printed because man thinks the browser could not be opened).

Note, also, that the TMP environment variable can be used to tell man where to create its temporary data.

Finally, the chosen workaround can be conveniently made into an alias or a function along the lines of:

alias man='BROWSER="${BROWSER:-firefox} %s && false" man'

See also, for alternative ways to view man pages as HTML:

5
  • If I unset the BROWSER variable before running the command, the html file is not deleted and the command fails with man: no browser configured, so cannot show HTML output. So it is indeed a race condition. Looking in the source, you see where they create the folder and file, and finally when they think the browser is closed, they remove the folder. It looks like it has been reported
    – smac89
    Apr 27, 2021 at 17:57
  • I will see if firefox has an option to not fork when being opened
    – smac89
    Apr 27, 2021 at 18:00
  • @smac89 The issue seems to only concern man pages opened in existing browser instances. A clean solution is unlikely to exist, in that case the process started by man can only exit; the file given to it as an argument is opened by a different process after some inter-process communication man can't have knowledge of/control on.
    – fra-san
    Apr 27, 2021 at 20:53
  • A clean solution can exist: Cache the opened man pages. It not only solves the problem, but can also provide a means for reducing the number of times the same html page is regenerated. You can use the stat of each file to determine if it's been in the cache for too long, then create a new copy. The last solution seems it would be the best
    – smac89
    Apr 27, 2021 at 22:19
  • Another option is if there is a MAN_BROWSER environment variable that mandb reads and only falls back to BROWSER if this is not defined. Then we can use that to setup any custom options required by the browser.
    – smac89
    Apr 27, 2021 at 22:30

You must log in to answer this question.

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