2

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.

2
  • You are setting 1 to the log file and then in the next iteration setting 3 to where 1 points. Commented Jul 16, 2015 at 13:23
  • Thank you, I was not aware it works like that (1 to log, 3 to 1...) Commented Jul 16, 2015 at 20:42

3 Answers 3

4

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.

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

Comments

2

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

1 Comment

Thank you for the explanation. I apologize if my explanation was not clear about the problem, but I sure did not intentionally "not disclosing all information"
1

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:

  • run the redirection and associated commands in a subshell, so that when it exits, you're still dealing with the original streams
  • treat redirection like registers to be saved in a function call - push them to a temporary (as in your &3 above) and then restore them after the call.

2 Comments

Thank you, but I will be using it many times. The script is big, this one is just to represent a problem. I do not like the idea to use redirection all over the place. There is also many calls to the function.
Thank you for pointing to direction, I do not know jet how to work with subshell or registers. I will look into it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.