1

I want to log stdout and stderr with timestamp to a log file and view it on screen. So I redirect stderr to stdout, add the timestamp with awk und tee it to log file. But there is a problem to get the correct error code.

Here an example without logging:

$ less notexists.txt
notexists.txt: No such file or directory
$ echo $?
1

The error code is correct

Here the example with logging:

$ less notexists.txt 2>&1 | awk '{ print strftime("[%Y-%m-%d %H:%M:%S]"), $0; fflush(); }' | tee -a log.txt
[2017-10-23 17:19:59] notexists.txt: No such file or directory
$ echo ${PIPESTATUS[*]}
0 0 0

The error codes of all three sections are 0, but in the first section should be a 1. I think the problem could be the redirection of stderr.

Is there a solution to log stdout and stderr with timestamp to a log file and view it on screen and get the correct error code?

Is it possible to duplicate stderr instead of redirect it?

1
  • 1
    The issue is with less having something other than a terminal as its standard output; try { less noexists.txt; echo $?; } | cat. Commented Nov 3, 2017 at 9:09

1 Answer 1

1

Apparently, less doesn't have a non-zero exit status if its standard output is not a terminal. If you force it

$ less notexists.txt  2>&1 > /dev/tty | awk '{ print strftime("[%Y-%m-%d %H:%M:%S]"), $0; fflush(); }' | tee -a log.txt
#                          ^^^^^^^^^^

you'll get the expected exit status, although you'll no longer get the standard output in your log file.


Here is, I think, the relevant code from less v487:

if (!is_tty)
        {
                /*
                 * Output is not a tty.
                 * Just copy the input file(s) to output.
                 */
                SET_BINARY(1);
                if (nifile() == 0)
                {
                        if (edit_stdin() == 0)
                                cat_file();
                } else if (edit_first() == 0)
                {
                        do {
                                cat_file();
                        } while (edit_next(1) == 0);
                }
                quit(QUIT_OK);
        }

So when standard output is not a terminal, less simply behaves like cat, except it ignores any errors trying to open its input. Regardless of what happens, it just exits 0.

Arguably, this is a bug, but I have spent all of 2 minutes looking at the source code, so I don't know if there is a rationale for this behavior.

Sign up to request clarification or add additional context in comments.

1 Comment

I've submitted a bug report; I'll report back with the maintainer's thoughts.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.