Friday 15 February 2013

How to display percentages in man pages

On many GNU/Linux distributions, man pages are displayed through the "less" pager. I was finding that it was not displaying percentages in man pages. This was due to the fact that the less process was reading its input through a pipe and did not have the whole file loaded.

There is a simple fix (which nonetheless took me a long time to find). Set "LESS=+p" as an environment variable. Then the "p" command will be executed whenever less starts up, which has the effect of loading the whole file. This command is to go to a position in the file marked by a certain percentage, so the whole file must be loaded to know where this is. We are going to 0% in the file, so loading the whole file shouldn't be necessary (as we are not moving anywhere), but less does this anyway.

Obviously, this should be unset if you are doing something like viewing the output of a process through less.

Thursday 7 February 2013

Pipeline filter to allow changing stdout of a process while it is still running

On a Unix-style system, running processes write characters to a location called the standard output. By default, these will appear on a terminal, as text for the user to see. However, it's possible to redirect the standard output to a file, or to be the input for another process.

It may occasionally be useful to be able to redirect the standard output after a process has already started. I'm sure that others have done similar things before, but I couldn't find exactly what I was looking for.

For this purpose, I wrote the following bash script, saved as "MovableStdout.sh":

new_stdout_pipe=~/ChangeTerminal

redirect () {
        read new_stdout <$new_stdout_pipe
        exec >$new_stdout
}

trap redirect SIGUSR1

while true; do
        if ! read line; then
                exit;
        fi
        echo $line
done

To use this, a named pipe (a FIFO) must be created, e.g. by running "mkfifo ~/ChangeTerminal". This pipe will be used to communicate with the running script.

Use it by running

$ program | bash MovableStdout.sh

The program will run and the script will copy the stdout from the program to the terminal.

If we later wish to change where what is written to stdout goes, we may do this in a two step process. For example, if we are in another terminal, and wish to divert the output to the current terminal, we may do:
$ echo `tty` >~/ChangeTerminal &
$ ps -C bash
TT       USER       PID COMMAND
tty2     root      1457 -bash
pts/0    g         1875 /bin/bash
pts/1    g         2638 /bin/bash
pts/2    g         3117 /bin/bash
pts/3    g         3774 /bin/bash
pts/4    g         3150 /bin/bash
pts/5    g         3162 /bin/bash
pts/6    g         3808 /bin/bash
pts/7    g         3937 /bin/bash
pts/7    g         3950 bash MovableStdout.sh
$ kill -USR1 3950
(The exact processes listed will obviously be different.) The new output file name is placed onto the pipe, and then the script is signalled to read the file name from the pipe. The script catches this signal and redirects its output to the new file.

A limitation of this script is that you can only have one running instance of it at a time, otherwise you will have multiple running scripts trying to read from the same pipe. However, it could easily be altered to, for example, read the name of the pipe as a command-line parameter.

I was able to use this script to redirect the error messages from my X11 window manager to an xterm window.