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
Differencebetween "Var=${Var:-Word}" and "Var=${Var:=Word}"
Why Do I Get "Suspended (Tty Output)" in One Terminal But Not in Others
Bash - Surround All Array Elements or Arguments with Quotes
How to Install Influxdb in Windows
Fallocate() Command Equivalent in Os X
Linux Run Kernel Probe Systemtap Script Failed with Semantic Error: No Match"
Populate a Ms Access Database in Linux
Nasm - Symbol 'Printf' Causes Overflow in R_X86_64_Pc32 Relocation
How Are Threads/Processes Parked and Woken in Linux, Prior to Futex
Tomcat 7 with Java 8 on Windows and Linux
Unix 'Alias' Fails with 'Awk' Command
Could Not Load Shared Library Symbols for Linux-Vdso.So.1. While Debugging
Check If a Program in a Specific Path Is Running
Can 'Connect' Call on Socket Return Successfully Without Server Calling 'Accept'
Error: Clgetplatformids -1001 When Running Opencl Code (Linux)