Home > Software design >  How do I ask nohup not to redirect stderr to stdout if it is detached from terminal?
How do I ask nohup not to redirect stderr to stdout if it is detached from terminal?

Time:05-09

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 &
  • Related