Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to connect more than the two standard streams to a terminal in Linux?

Consider the following simple program, and suppose it is in a file called Test.c.

#include <stdio.h>

int main(){
    fprintf(stdout, "Hello stdout\n");
    fprintf(stderr, "Hello stderr\n");
}

Suppose I compile this program into an executable called Test and run it as follows.

./Test > Out 2> Err

After this run, I will have two files Out and Err, which will contain the two messages respectively.

This is wonderful because I can have two different types of messages normally printed to the console, and then filter one or both by using bash redirection. However, the fact that I can only do this kind of filtering with two file descriptors seems very limiting.

Is there some way to open a third or nth file descriptor which points at the terminal output, so I could filter it separately?

The syntax might be something like this.

./Test > Out 2> Err 3> Err2

I speculate that bash may have some rudimentary support for this because of the following test, which seems to imply that bash will treat the number after a & as a file descriptor.

$ ./Test >&2
Hello stdout
Hello stderr
$ ./Test >&3
bash: 3: Bad file descriptor
like image 265
merlin2011 Avatar asked Sep 29 '22 14:09

merlin2011


1 Answers

At a shell, running either

exec 3>/dev/tty

...or...

exec 3>&1

...will open file descriptor 3, pointing it to your TTY explicitly (in the first case), or to the location at which stdout is currently writing to (in the second).


If you want to use this in a program, I would strongly suggest taking an FD number to write extra logs to as an optional argument:

yourprogram --extra-logs-fd=3

...combining that output with stderr, or suppressing it entirely (as appropriate) if no such option is given. (A user who wanted extra logging to go to stdout could thus use --extra-logs-fd=1, or --extra-logs-fd=2 for stderr).

Even better, if your only target OS is Linux, is just to accept a filename to write to:

# to write to a file
yourprogram --extra-logs=extra_logs.txt

# to write to FD 3
yourprogram --extra-logs=/dev/fd/3

# to write to a tee program, then to stderr (in ksh or bash)
yourprogram --extra-logs=>(tee extra_logs.txt >&2)

...of course, you can do all that with the FD mode (just redirect 3>extra_logs.txt in your shell in the first case, and 3> >(tee extra_logs.txt >&2) in the third), but this makes you do the work of managing FD numbers by hand, and with what advantage?

like image 88
Charles Duffy Avatar answered Oct 11 '22 03:10

Charles Duffy