Reputation: 587
I am trying to understand redirecting the output.
I have the code:
#!/bin/bash
function function1 () {
log=${1}.log
exec 3>&1
exec 1>>$log
exec 2>&1
echo checking $log >&3
echo txt to $log
}
function1 log1
function1 log2
exit 0
the output that I get is:
checking log1.log
and file log1.log
with content
txt to log1.log
checking log2.log
and file log2.log
with content
txt to log2.log
what I really want is file log1.log
with content
txt to log1.log
and file log2.log
with content
txt to log2.log
and output to terminal to be.
checking log1.log
checking log2.log
How can I do that, please ?
I know I can use function1 log1 > log1.log 2>&1
, but than I can not redirect echo back to terminal in function1, I can but it is similar result.
Upvotes: 2
Views: 1427
Reputation: 12255
If you want to set stdout and stderr and then restore them in the function do:
function function1 () {
log=${1}.log
exec 4>&2 3>&1 1>>$log 2>&1 # save 1 and 2 to 3 and 4
echo checking $log >&3
echo txt to $log
exec 1>&3 2>&4 3>&- 4>&- # restore 1 and 2
}
The 3>&-
closes 3, just for completeness.
Upvotes: 4
Reputation: 11216
No idea why you would want to do it this way and the other answer is a much better way unless you are not disclosing all information, but the problem is with your understanding of how file descriptors work.
First time
exec 3>&1 ## Assign 3 to where 1 is currently pointing which is /dev/tty
exec 1>>$log ## assigns 1 to point to logfile
exec 2>&1 ## Assigns stderr to the 1 which currently points at the logfile
Second time
exec 3>&1 ## Assign 3 to where 1 is currently pointing which is the old logfile
exec 1>>$log ## assigns 1 to point to new logfile
exec 2>&1 ## Assigns stderr to the 1 which currently points at the new logfile
As you can see the file descriptors remember where they are pointing and simply point to whatever you tell them to.
If you want to do it this way, instead of redirecting to 1, just redirect straight to /dev/tty, as unlike 1 this will never change(hopefully!).
#!/bin/bash
function function1 () {
log=${1}.log
exec 3>/dev/tty
exec 1>>$log
exec 2>&1
echo checking $log >&3
echo txt to $log
exec 1>/dev/tty # Probably want this line as well so your not writing to
# the logfile for the rest of the script
}
function1 log1
function1 log2
exit 0
Upvotes: 2
Reputation: 38118
This should do it
#!/bin/bash
function function1 () {
log=${1}.log
echo checking $log
echo txt to $log >$log
}
function1 log1
function1 log2
exit 0
There's no reason to store changes to any particular file descriptor, when you're only using the changed destination once.
If you do want to use that approach, say because you're redirecting a lot of commands, you have at least 2 options:
&3
above) and then restore them after the call.Upvotes: 1