5

I am trying to log output from some shell scripts of mine to a file, and I want the timestamp prepended to each line. From what I understood, that's what logger(1) is for, but I don't want the output to go to /var/log/messages, and I can't see that this is possible using logger. I'm using Debian by the way.

What is the best way to do this?

—Oliver

1

4 Answers 4

6

logger's function is actually to shunt messages to syslog; default configs will prepend a timestamp and write the logs out to /var/log/messages, but that doesn't mean that logger's purpose is to prepend a timestamp.

One way to handle this would be to modify your syslog configs such that your messages routed via logger go to a special file - use the "-p" flag to logger to stipulate a facility.priority pair (perhaps one of the user[1..7] facilities), and configure your syslogd to log that facility to a special file.

Alternatively, you could whip up a quick shell function to simply prepend the timestamp:

Bodacious:~ james$ timestamp () {
> f=`date`
> echo $f $*
> }
You have new mail in /var/mail/james
Bodacious:~ james$ timestamp a line of logs
Tue 18 Jan 2011 22:40:24 EST a line of logs
Bodacious:~ james$ 

On my system, this is going to result in the shell forking /bin/date once per line of output. This is inefficient, but probably acceptable at small scales.

2
  • Thanks for a good answer :) This was my original idea, but I thought "there has to be a program out there that does this already"… but clearly not! Or not one that's commonly used anyhow. Out of curiosity, what are the "user[1..7] facilities" you refer to?
    – obeattie
    Jan 18, 2011 at 21:57
  • In attempting to provide an authoritative reference for my answer, I found out that I was a bit wrong. "Facilities" are one of the ways syslog segments the messages it processes. There are 23 facilities defined - mostly for types of log messages that were common when syslog was created (lpr, ftp, cron), a couple to be generic buckets (messages, system) - but there are 8 facilities called local0 through local7 (not user1 through user7 as I originally stated) intentionally designed for local uses. See RFC5424 for the full list of facilities May 2, 2011 at 23:31
4

I needed something like that, and google got me here. Using something like syslog is definitely an overkill for just trying out to time something, and the printout-every-second is too inconvenient.

Here's a one-liner that seems to work fine:

cmd | { while read R; do echo "$(date +%s) $R"; done }

and a variant that prints the time it took to produce each line:

cmd | { T=$(date +%s); while read R; do T2=$(date +%s); echo "$((T2-T)) $R"; T=$T2; done }

(This is using seconds, probably not too hard to throw in %N in there, but at that level a shell solution is probably not the right tool anyway.)

0

You could use -t to tag each line, and then get your syslog server to filter to a different file based on that tag.

(Edited to take out incorrect reference to -f flag)

2
  • That's not what -f does. It uses the contents of the file as the message portion of the log entry. Jan 18, 2011 at 14:44
  • My apologies! Misread the man page. However, the second part of the answer stands, so I've editted it to include just that. Jan 18, 2011 at 14:48
0

Using the answer from Command to prepend string to each line?, I found this the easiest solution:

cmd | sed "s/^/`date +'%a %b %d %k:%M:%S'` /"
7
  • No, this is broken: it appends the same date to all lines. Feb 8, 2012 at 2:20
  • Well, it's broken if you want to run an entire log-generating process through it. I'm using it as I generate each line. Feb 8, 2012 at 4:40
  • If you're using it for a single line you don't need any pipe -- it's almost exactly the same as date +...; cmd. The only difference is that you get a newline from date which you can remove in the usual ways. Feb 8, 2012 at 16:25
  • The usual ways being sed?:-) Feb 9, 2012 at 11:25
  • That would be one way ... but you're not using it. Your line uses backticks in a way that already swallows the newline. Here's a complete line that shows what I mean: echo -n "$(date +%s) "; cmd -- note that there are no pipes and no external subprocess other than date. Feb 9, 2012 at 17:43

You must log in to answer this question.

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