質問

This is a simplified version of a script I use: In its simplified version tt should read the file input line by line and then print it to the standard output and also write to a file log.

input file:

asas
haha
asha
hxa

The script (named simple):

#!/bin/bash

FILE=input
logfile="log"

exec > >(tee "$logfile")   # redirect the output to a file but keep it on stdout
exec 2>&1

DONE=false
until $DONE; do
read || DONE=true
  [[ ! $REPLY ]] && continue                      #checks if a line is empty

  echo "----------------------"

  echo $REPLY

done < "$FILE"
echo "----------------------"
echo ">>> Finished"

The output (on console):

-bash-3.2$ ./simple
-bash-3.2$ ----------------------
asas
----------------------
haha
----------------------
asha
----------------------
hxa
----------------------
>>> Finished

At this time I need to press enter to terminate the script. Notice that a command prompt -bash-3.2$ showed up during execution.

I checked that those lines are to blame:

exec > >(tee "$logfile")   # redirect the output to a file but keep it on stdout
exec 2>&1

Without them the output is as expected:

-bash-3.2$ ./simple
----------------------
asas
----------------------
haha
----------------------
asha
----------------------
hxa
----------------------
>>> Finished
-bash-3.2$

What is more I don't need to press enter to terminate the script. Unfortunately I need saving the output both to the console (stdout) and a log file.

How can this be fixed?

役に立ちましたか?

解決

You can use tee on the echo lines directly.

For example:

[ben@lappy ~]$ echo "echo and save to log" | tee -a example.log
echo and save to log
[ben@lappy ~]$ cat example.log 
echo and save to log

The -a argument to tee will append to the log.

他のヒント

If you just need it to pause and wait for user input use the pause command:

 pause

What's happening is that tee "$logfile" is being run asynchronously. When you use process substitution like that, the main script doesn't wait for the process to exit.

So the until loop runs, the main script exits, the shell prints the prompt, and then tee prints its output.

You can see this more easily with:

echo Something > >(sleep 5; cat)

You'll get a command prompt, and then 5 seconds later Something will appear.

There was a thread about this behavior in comp.unix.shell a couple of years ago. See it here

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top