4

I am running several tasks simultaneously at background.

command_a | tee > command_a.log &
command_b | tee > command_b.log &

If everything is fine, then messages will be saved to log files.

If something wrong, it will print errors on screen.

But command_a and command_b are quite similar, it’s hard to tell which error message is generated by which command.

Can I add prefix string to error messages, like:

command_a: error 123
command_b: error 456
command_a: error 256
command_a: error 555
command_b: error 333

2 Answers 2

6

bash process substitutions:

command_a 2> >(sed 's/^/command_a: /' >&2) > command_a.log &
command_b 2> >(sed 's/^/command_b: /' >&2) > command_b.log &

You don't need to pipe to tee if you just redirect it's stdout to a file.

You can even do fancy stuff like print a timestamp:

$ {
  date
  echo stdout
  sleep 3
  echo stderr >&2
} 2> >(gawk '{print "foobar:", strftime("[%F %T]", systime()), $0}' >&2) > file.log
foobar: [2015-02-24 11:43:32] stderr
$ cat file.log
Tue Feb 24 11:43:29 EST 2015
stdout

Stick it in a function for re-use:

log_stderr() {
    gawk -v pref="$1" '{print pref":", strftime("%F %T", systime()), $0}' >&2
}

command_a > command_a.log 2> >(log_stderr "command_a")
3
  • For my understanding, 2> redirect all stderr, >() is redirect to a command, sed used to add prefix, after sed message become stdout, >&2 convert message back to stderr, finally save to log file. My understanding is correct? Thanks! @glenn jackman
    – Fisher
    Feb 24, 2015 at 18:41
  • yes, except >() is called a "process substitution" Feb 24, 2015 at 18:42
  • @Fisher you may want to accept an answer if it answers your question (that's the Stack Overflow way of saying "Thanks")
    – umläute
    May 29, 2017 at 9:18
0

Prefix output

{
  echo foo
  sleep 1
  echo bar >&2
} \
   > >(sed "s/^/$(date '+%Y-%m-%d %H:%M:%S') [INF] /") \
  2> >(sed "s/^/$(date '+%Y-%m-%d %H:%M:%S') [ERR] /" >&2)

Prefix output and redirect to a log file

Redirect script to test.log file:

{
  echo foo
  sleep 1
  echo bar >&2
} \
   > test.log \
  2>&1 \
   > >(sed "s/^/$(date '+%Y-%m-%d %H:%M:%S') [INF] /") \
  2> >(sed "s/^/$(date '+%Y-%m-%d %H:%M:%S') [ERR] /" >&2)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .