opaquejacob
opaquejacob

Reputation: 35

Bash date command ongoing update

Is there a way for date (or something similar) in bash to have an ongoing update each time a new line is piped to it?

I'm trying to take ongoing output, pipe through awk to prepend a timestamp, and then write that to a log file named with the correct date of write (for example log.2018-06-21). When the new day arrives, the output should automatically start writing to the new day's log file.

Put simply, ./my_server | awk >> log.date-of-write

Here is what I tried (with format %T instead of %F for test purposes):

$ awk '{ print strftime("%F %T %Z:  ") $0; fflush(); }' |& tee -a "log.$(date +"%T")"
test1
2018-06-21 22:56:38 UTC:  test1
test2
2018-06-21 22:56:40 UTC:  test2
test3
2018-06-21 22:56:42 UTC:  test3
^C
$ ls
log.22:56:36
$ cat log.22\:56\:36 
2018-06-21 22:56:38 UTC:  test1
2018-06-21 22:56:40 UTC:  test2
2018-06-21 22:56:42 UTC:  test3
$

All the tests were written to the same file, because the original time was used in the format.

Upvotes: 1

Views: 189

Answers (1)

Charles Duffy
Charles Duffy

Reputation: 295353

Yes, this can be done; what you need to do is periodically generate a new filename, check whether it's the same as the name you're writing output to, and re-open your stdout to point to the new location if they differ.

Note that the printf %(...)T idiom used in lieu of date is a recent feature, and may not be present if you're running an old version of bash. (You certainly can switch to date, but doing so would be much slower).

log_with_rotation() {
  local outfile_name outfile_curr line
  outfile_curr=
  while IFS= read -r line; do
    printf -v outfile_name 'log.%(%H:%M:%S)T' -1
    if [[ $outfile_name != "$outfile_curr" ]]; then
      outfile_curr=$outfile_name
      exec >"$outfile_name"
    fi
    printf '%s\n' "$line"
  done
}

When I run this:

your_program() {
  printf '%s\n' "Cluster one, line one" "Cluster one, line two"
  sleep 2
  printf '%s\n' "Cluster two, line one" "Cluster two, line two"
}

your_program | log_with_rotation

...I get two output files:

$ grep Cluster log.*
log.17:09:38:Cluster one, line one
log.17:09:38:Cluster one, line two
log.17:09:40:Cluster two, line one
log.17:09:40:Cluster two, line two

Upvotes: 1

Related Questions