[SOLVED] Problem in wait statement

Iam having a script which is used to load users and dumpfile in any given schema.Iam trying to autolog the script and have added two fucntion in it.

function init_stdout_redirect {
    OUT_LOG=$1
    OUT_PIPE=$(mktemp -u)
    # Create the output pipe
    mkfifo $OUT_PIPE
    # Save stdout and stderr as 3 and 4
    exec 3>&1 4>&2
    # Tee the output pipe into the log file
    tee -a $OUT_LOG < $OUT_PIPE >&3 &
    # Save tee's pid
    TEE_PID=$!
    # Redirect the output to the pipe
    exec > $OUT_PIPE 2>&1
}
###########################################################################
# restore_stdout
#
# Restore standard output
###########################################################################
function restore_stdout {
    exec 1>&3 3>&- 2>&4 4>&-
    wait $TEE_PID
    rm -f $OUT_PIPE
}

I have added these two function in the main script.The main script is having two wait command in it.As soon i run the script after adding and calling these two function the script is getting hanged after encoutering the first wait statement of main script.

When i try to check where it is getting stuck i found the process id and saw that it get stuck on process tee -a log file name..Iam not sure why it is getting stuck as it should come out of it. Could someone please help me on it.

A FIFO blocks until both ends have been opened. You can't do it one at a time; if you open the read-end first it will wait for the writer, if you open the write-end first it will wait for the reader.

You'll have to put one of the processes in the background first before you can open the other end.

Hello Corona

Actually these are the standard fucntion which we are using in all other scripts where it is working fine. Here the difference is that the main script is having two additional wait statement. I am already running the process in background as you could see in the function.

tee -a $OUT_LOG < $OUT_PIPE >&3 &

Once all the task is done I check the process and found that process which is not terminated is the one which is teeing the log.

tee -a logfilename

So Iam not sure where it is getting stuck.Could you Adivse me if their is soemthing wrong in this function.

Thanks in Advance.

That's the thing, it's not really running in the background -- yet. tee doesn't open $OUT_PIPE, redirections are the shell's job. Meaning, before the command gets put into the background, the shell has to open the fifo first. When it tries, it will deadlock, waiting for the other end to be opened.

So you need an entire background shell, not just a background process. It will open the fifo for tee, and your own shell will not need to wait for it. Once the files are opened, the extra shell's not needed and can leave, which is why I use exec instead of running tee directly -- it replaces that extra shell after it's done.

( exec tee -a $OUT_LOG < $OUT_PIPE >&3 ) &

Hi Corona,

I have tried that too but still getting the same issue. I have attched the entire Script. If possible please have a look at it.Somehow the scrit is getting hanged on the first wait statment in main script and when i check which process is going on its showing the Tee process only.

Thanks
Vikram

No, you have not. You did the exact same thing you did before. I suggest trying what I suggested above, for the reasons I stated above:

( exec tee -a $OUT_LOG < $OUT_PIPE >&3 ) &

Hi Corona,

I have tried the code changes which you asked me to try but still it got stuck on 1st wait process of the main script. Iam using this fucntion in other scripts but their it is perfectly working fine. Only for this function iam facing issue.

Iam using this code only

 # Tee the output pipe into the log file
   ( exec tee -a $OUT_LOG < $OUT_PIPE >&3 ) &

I am running this code in debug mode and attaching the same.

Thanks

It's getting stuck on wait? That makes sense, since it's not about to die. Okay then, you can remove it from the shell's control with disown.

Of course, this means you'll have to make sure you kill this process yourself when the shell quits, since it won't be under the shell's control any more. Closing the output pipe will probably do it, but if it hangs, wait a second then kill it.

( exec tee -a $OUT_LOG < $OUT_PIPE >&3 ) &
PID="$!"
disown
trap "exec 1>&-; exec 2>&-; sleep 1 ; kill $PID" EXIT

Hi Corona,

The script runs fine after this but i didn't found any DB Logs.Their was no log file created in the required folder.The script went fine on the terminal only.:frowning:

Thanks
Vikram

This works here:

#!/bin/sh

function init_stdout_redirect {
    OUT_LOG=$1
    OUT_PIPE=$(mktemp -u)

    # Create the output pipe
    mkfifo $OUT_PIPE

    # Save stdout and stderr as 3 and 4
    exec 3>&1 4>&2

    # Tee the output pipe into the log file
    ( exec tee -a $OUT_LOG < $OUT_PIPE >&3 ) &

    # Save tee's pid
    TEE_PID=$!

    trap "exec 2>&-; exec 1>&-; sleep 1 ; kill ${TEE_PID} ; rm -f ${OUT_PIPE}" EXIT

    # Redirect the output to the pipe
    exec > $OUT_PIPE 2>&1
 }

init_stdout_redirect log.file

echo asdf
echo qwertyuiop>&2
exit

The data shows up on screen and in the log file.

Iam afraid to tell its not working yet. Iam attaching the logs and the script which iam using.

+ init_stdout_redirect /apps/psr/database/logs/env53b_Refresh_2012-12-05-2346.log
+ OUT_LOG=/apps/psr/database/logs/env53b_Refresh_2012-12-05-2346.log
++ mktemp -u
+ OUT_PIPE=/tmp/tmp.XGCWt20093
+ mkfifo /tmp/tmp.XGCWt20093
+ exec
+ TEE_PID=20105
+ trap 'exec 2>&-; exec 1>&-; sleep 1 ; kill 20105 ; rm -f /tmp/tmp.XGCWt20093' EXIT
+ exec
+ exec tee -a /apps/psr/database/logs/env53b_Refresh_2012-12-05-2346.log
+ Get_Database_Variables_From_Env_Xml env53b
+ local function_name=Get_D

What i feel is the wait statement in the main build_environment script needs to be remove.

I forgot the disown.

I wouldn't remove the wait unless that's your code and not the rest of the script, I don't know what it was for.

function init_stdout_redirect {
    OUT_LOG=$1
    OUT_PIPE=$(mktemp -u)

    # Create the output pipe
    mkfifo $OUT_PIPE

    # Save stdout and stderr as 3 and 4
    exec 3>&1 4>&2

    # Tee the output pipe into the log file
    ( exec tee -a $OUT_LOG < $OUT_PIPE >&3 ) &

    # Save tee's pid
    TEE_PID=$!

    disown

    trap "exec 2>&-; exec 1>&-; sleep 1 ; kill ${TEE_PID} ; rm -f ${OUT_PIPE}" EXIT

    # Redirect the output to the pipe
    exec > $OUT_PIPE 2>&1
 }

Note: disown is bash/ksh93..

I was under the impression that shells without disown didn't need disown either...

OK, I see the script is ksh / bash syntax, I had looked at the shebang, which calls /bin/sh

Awesome Corona.It worked at last. This also means that their is no need of second fucntion as the TEE_PID job already killed thorugh the first function itself.

Thanks for explaining the code.

1 Like