Temporarily Redirect Stdout/Stderr

Temporarily Redirect stdout/stderr

To solve the issue that some function might have cached sys.stdout stream as a local variable and therefore replacing the global sys.stdout won't work inside that function, you could redirect at a file descriptor level (sys.stdout.fileno()) e.g.:

from __future__ import print_function
import os
import sys

def some_function_with_cached_sys_stdout(stdout=sys.stdout):
print('cached stdout', file=stdout)

with stdout_redirected(to=os.devnull), merged_stderr_stdout():
print('stdout goes to devnull')
some_function_with_cached_sys_stdout()
print('stderr also goes to stdout that goes to devnull', file=sys.stderr)
print('stdout is back')
some_function_with_cached_sys_stdout()
print('stderr is back', file=sys.stderr)

stdout_redirected() redirects all output for sys.stdout.fileno() to a given filename, file object, or file descriptor (os.devnull in the example).

stdout_redirected() and merged_stderr_stdout() are defined here.

Need a way to temporarily redirect STDOUT

You have to first save stdout (by linking it on fd #4 for instance)

exec 4<&1

Redirect stdout

exec 1>bar

And restore saved stdout

exec 1<&4

How could I temporary redirect stdout to a file in a C program?

On POSIX systems, you can do it as follows:

int bak, new;

fflush(stdout);
bak = dup(1);
new = open("/dev/null", O_WRONLY);
dup2(new, 1);
close(new);

/* your code here ... */

fflush(stdout);
dup2(bak, 1);
close(bak);

What you want is not possible in further generality.

Any solution using freopen is wrong, as it does not allow you to restore the original stdout. Any solution by assignment to stdout is wrong, as stdout is not an lvalue (it's a macro that expands to an expression of type FILE *).

Redirect stdout/stderr using dup2, then resinstate later

You must dup the initial file descriptors before your dup2, otherwise dup2 closes them and there is no way to recover them.

int stdout_copy = dup(STDOUT_FILENO);
dup2(nf, STDOUT_FILENO);

/* do something with stdout */

dup2(stdout_copy, STDOUT_FILENO);
close(stdout_copy);

Throw in error handling, add fflush calls to ensure you don't leave data unwritten in stdlib buffers and you should be good.

Redirect standard output to file and re-establish the standard output with function

I finally got the correct answer, so here is how to temporarily redirects the standard output to a file name "file", then executes the function f, then re-establishes the original standard output:


void redirect_stdout (void (*f)(void), char *file)
{
int fd = open(file, O_CREAT | O_TRUNC | O_WRONLY, 0644);
int savefd = dup(1);
dup2(fd, 1);
f();
dup2(savefd, 1);
close(fd);
close(savefd);
}

Temporary redirection of stderr in a bash script

Another option is:

exec 3> /dev/stderr 2> /dev/null
progname >& ./tmp/run.txt && run_status='OK'
exec 2>&3

Or even

exec 3>&2 2> /dev/null
progname >& ./tmp/run.txt && run_status='OK'
exec 2>&3

That way the script preserves the separation of stdout and stderr for the script (ie. the scripts stdout and stderr can be redirected separately.

Redirect STDOUT to new window, STDERR to same new window and also a log file

You can use tee with process substitution, like this:

your_cmd 1> >(tee -a /dev/pts/2 >> out.log) 2> >(tee -a /dev/pts/2 >> err.log)

Alternatively, you can use the process substitution only for stderr - because it is needed - and redirect stdout, just as normal, through a pipe:

your_cmd 2> >(tee -a /dev/pts/2 >> err.log) | tee -a /dev/pts/2 >> out.log

How to redirect and append both standard output and standard error to a file with Bash

cmd >>file.txt 2>&1

Bash executes the redirects from left to right as follows:

  1. >>file.txt: Open file.txt in append mode and redirect stdout there.
  2. 2>&1: Redirect stderr to "where stdout is currently going". In this case, that is a file opened in append mode. In other words, the &1 reuses the file descriptor which stdout currently uses.


Related Topics



Leave a reply



Submit