We know that &> outfile
redirects both stdout
and stderr
to outfile
in a UNIX shell. But how does the shell implement this? I write a naïve test:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
int fd = open("tmpf", O_CREAT | O_TRUNC | O_WRONLY, 0644);
// redirect stdout to file
dup2(fd, 1);
close(fd);
// redirect stderr to stdout
dup2(2, 1);
close(2);
// print stuff to file
fprintf(stdout, "stdout string\n");
fprintf(stderr, "stderr string\n");
}
It simply redirects stdout
to the file and then redirects stderr
to stdout
. But this doesn't work. The above code produces
$ ./a.out
stdout string
$ cat tmpf
$
If we exchange the order of stdout->file
and stderr->stdout
, it gives the following result
$ ./a.out
$ cat tmpf
stdout string
$
CodePudding user response:
Don't close your destination FDs. The only FD you should close is the handle on tmpf
; both stdout and stderr need to be open to be able to write to them.
Also, it should be dup2(1,2)
to copy stdout to stderr -- coping stderr to stdout (as the original code does) discards your handle on tmpf
.
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
int fd = open("tmpf", O_CREAT | O_TRUNC | O_WRONLY, 0644);
// copy FD to stdout ("redirect stdout to fd")
dup2(fd, 1);
// fd was copied to stdout so we don't need the original
close(fd);
// copy stdout fd to stderr ("redirect stdout to stderr")
dup2(1, 2);
// print stuff to file
fprintf(stdout, "stdout string\n");
fprintf(stderr, "stderr string\n");
}
Also see this running in an online sandbox at https://replit.com/@CharlesDuffy2/KnowingWobblyFibonacci#main.c (you can use "Show files" to see the resulting tmpf
file in output).