After Using 'Exec 1>File', How to Stop This Redirection of the Stdout to File and Restore the Normal Operation of Stdout

After using `exec 1 file`, how can I stop this redirection of the STDOUT to file and restore the normal operation of STDOUT?


Q1

You have to prepare for the recovery before you do the initial exec:

exec 3>&1 1>file

To recover the original standard output later:

exec 1>&3 3>&-

The first exec copies the original file descriptor 1 (standard output) to file descriptor 3, then redirects standard output to the named file. The second exec copies file descriptor 3 to standard output again, and then closes file descriptor 3.

Q2

This is a bit open ended. It can be described at a C code level or at the shell command line level.

exec 1>file

simply redirects the standard output (1) of the shell to the named file. File descriptor one now references the named file; any output written to standard output will go to the file. (Note that prompts in an interactive shell are written to standard error, not standard output.)

exec 1>&-

simply closes the standard output of the shell. Now there is no open file for standard output. Programs may get upset if they are run with no standard output.

Q3

If you close all three of standard input, standard output and standard error, an interactive shell will exit as you close standard input (because it will get EOF when it reads the next command). A shell script will continue running, but programs that it runs may get upset because they're guaranteed 3 open file channels — standard input, standard output, standard error — and when your shell runs them, if there is no other I/O redirection, then they do not get the file channels they were promised and all hell may break loose (and the only way you'll know is that the exit status of the command will probably not be zero — success).

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);
}

Linux - Redirecting part of output to a file

You can do:

#!/bin/bash

# Link file descriptor #6 with stdout/stderr
exec 6>&1 2>&1

exec 1> record.log 2>&1
echo begin redirecting

# restore and close file descriptor #6
exec 1>&6 2>&1 6>&-

# from the script above, 'begin redirecting' will be redirected to record.log
# then we want to disable the redirecting and restore the STDOUT&STDERR

echo return to STDOUT and STDERR

Redirect stderr to terminal and also file in bash

Yes, the tee command allows you to direct output to one or more files, as well as stdout.

As you pointed out in a comment, this doesn't work by itself because of the exec command.

This should do what you want:

exec 3>&1 1>test.log
echo "Check if this line is going to test.log"
exec 1>&3 3>&-
echo "Maybe this should go to stderr" | tee -a test.log >> /dev/stderr

I got the information about the way to restore stderr by properly setting up the original exec, from here, and combined it with tee.

How to redirect output of an entire shell script within the script itself?

Addressing the question as updated.

#...part of script without redirection...

{
#...part of script with redirection...
} > file1 2>file2 # ...and others as appropriate...

#...residue of script without redirection...

The braces '{ ... }' provide a unit of I/O redirection. The braces must appear where a command could appear - simplistically, at the start of a line or after a semi-colon. (Yes, that can be made more precise; if you want to quibble, let me know.)

You are right that you can preserve the original stdout and stderr with the redirections you showed, but it is usually simpler for the people who have to maintain the script later to understand what's going on if you scope the redirected code as shown above.

The relevant sections of the Bash manual are Grouping Commands and I/O Redirection. The relevant sections of the POSIX shell specification are Compound Commands and I/O Redirection. Bash has some extra notations, but is otherwise similar to the POSIX shell specification.

How to redirect output of systemd service to a file

I think there's a more elegant way to solve the problem: send the stdout/stderr to syslog with an identifier and instruct your syslog manager to split its output by program name.

Use the following properties in your systemd service unit file:

StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=<your program identifier> # without any quote

Then, assuming your distribution is using rsyslog to manage syslogs, create a file in /etc/rsyslog.d/<new_file>.conf with the following content:

if $programname == '<your program identifier>' then /path/to/log/file.log
& stop

Now make the log file writable by syslog:

# ls -alth /var/log/syslog 
-rw-r----- 1 syslog adm 439K Mar 5 19:35 /var/log/syslog
# chown syslog:adm /path/to/log/file.log

Restart rsyslog (sudo systemctl restart rsyslog) and enjoy! Your program stdout/stderr will still be available through journalctl (sudo journalctl -u <your program identifier>) but they will also be available in your file of choice.

Source via archive.org

Redirect stderr and stdout in Bash

Take a look here. It should be:

yourcommand &> filename

It redirects both standard output and standard error to file filename.

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



Related Topics



Leave a reply



Submit