2022-11-19

How to redirect output of background bash pipeline in real time

I have a long-running bash script (like a daemon), which may emit output to both stdout and stderr.

I have these requirements:

  • prepend every output line with a string (e.g. date, time of the log entry and other info)
  • redirect all output into a log file
  • output redirection must be real-time (i.e. log file must be filled while process is running)
  • the process needs to run in background

This is what I've achieved so far:

myscript="script_name"
log_file="/tmp/blabla"

prepend_info() {
    xargs -d '\n' printf "$(date +'%b %d %T') $HOSTNAME $myscript: %s\n"
}

script -q -c "$myscript" /dev/null 2>&1 | prepend_info > "$log_file" 2>&1 &

The problem is that the log file gets filled only after my script has terminated, but I want to see output while it's running instead.

If I remove |& prepend_info it works as expected, but I need that additional info into the log file as well.

It seems like the pipe only gets executed after the first command terminates.

Is there some way to modify the output of a background script and redirect it into a file while it's running?

I need to be as compatible as possible, and I can only use simple bash commands. For example, I cannot use ts because it's not always available and also I don't need only the timestamp but other info as well.

UPDATE: The only solution I found so far (it solves everything, also the issue with date) is the following.

myscript="script_name"
log_file="/tmp/blabla"

exec_script() {
    rm -f "$log_file"
    local out_log=<($myscript 2>&1)
    while read -r line; do
        echo "$(date +'%b %d %T') $HOSTNAME $myscript: $line" >> $log_file
    done < "$out_log"
}

exec_script &

If anyone has a better solution, I'm all ears.



No comments:

Post a Comment