This question looks naive but I can't find the answer after half an hour of intensive searching. Basically I do not want stderr messages to sneak into my result file.
$nohup ./a.out | gzip -c > result.txt.gz 2>log.txt &
nohup: ignoring input and redirecting stderr to stdout
$zcat result.txt.gz
this is stderr output.
this is stdout output.
The a.out file was compiled from the following test.c by "cc test.c",
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main(int argc, char *argv[])
{
fprintf(stderr, "this is stderr output.\n");
fprintf(stdout, "this is stdout output.\n");
return 0;
}
But I do not want stderr message to be in the result file result.txt.gz. It should be in log.txt but that file is empty. Thank you!
CodePudding user response:
That error redirection actually applies to the gzip
command, not /.a.out
. What you're looking for is ./a.out 2> log.txt | gzip -c > result.txt.gz
.
CodePudding user response:
@fireshadow52 already posted a working solution, but I wanted to add some details.
A pipe connects the stdout
of one process to the stdin
of another. That is, it doesn't pipe stderr
of the first command to the stdin
of the second one. That means, as far as nohup
is concerned, in the original command
nohup ./a.out | gzip -c > result.txt.gz 2>log.txt &
stderr
of ./a.out
is still connected to the terminal, so nohup
takes care of the redirection for you and any output on stderr
gets redirected to nohup.out
. If stdout
or stderr
had still been output to the terminal, that would've (possibly) interfered with the output of other commands sharing the terminal. From man nohup
:
If standard input is a terminal, redirect it from an unreadable file. If standard output is a terminal, append output to 'nohup.out' if possible, '$HOME/nohup.out' otherwise. If standard error is a terminal, redirect it to standard output. To save output to FILE, use 'nohup COMMAND > FILE'.
With this in mind, it becomes clear that you need to redirect stderr
before the pipe and end up with @fireshadow52's solution:
nohup ./a.out 2> log.txt | gzip -c > result.txt.gz &
As a slight variation of the accepted answer, one could also use process substitution instead of a pipe (although I'd argue the latter is more readable):
nohup ./a.out 2> log.txt > >(gzip -c > result.txt.gz) &
In this case, you want to redirect stderr
and stdout
to different destinations, but if you want all output to go through a pipe, just redirect stderr
to stdout
before the pipe:
nohup ./a.out 2>&1 | gzip -c > result.txt.gz 2>log.txt &