[ale] line timestamp command

Ed Cashin ecashin at noserose.net
Thu Nov 14 15:33:14 EST 2013


At this point, we're probably past the point of diminishing returns, but I
think that if I wanted to get really picky, I'd opt for block buffering
with fflush after each semantic unit.  Since the timestamp doesn't complete
the semantic unit, which is "{timestamp}: {message}\n", I'd try to fflush
after each "{timestamp}: {message}\n" pair.

All this would only matter if the utility is for general use with unknown
specific use cases.  Then there's a possibility, for example, that the
utility will be used in a situation where multiple processes are using the
utility and appending its output to a single file.  In that case, you
wouldn't want the output of the two producers to get mixed up.

I mean, your program was probably fine as it stood originally, but I just
happened to remember being surprised by the block buffering when I first
saw it.  So it seemed worth bringing up.



On Thu, Nov 14, 2013 at 1:59 PM, Horkan Smith <ale at horkan.net> wrote:

> Interesting.  I'd not noticed that behavior, thanks for pointing it out!
>
> I think the reason we're seeing the timestamp come out is the call to
> fflush() - which means I could also fix this by adding:
>
>       fputc(ch, outstream);
>       lastch = ch;
>
> +     if ('\n' == lastch) {
> +        fflush(outstream);
> +     }
>
>    }
>
> Which in turn would mean I could probably drop the fflush() after the
> timestamp.
>
> I'm not sure which is the 'better' solution, as they both seem to work.
>  Any thoughts?
>
> thanks!
>    horkan
>
> On Thu, Nov 14, 2013 at 08:59:05AM -0500, Ed Cashin wrote:
> > Hi, Horkan.
> >
> > That reminds me of an issue I encountered when writing this kind of C
> > program.  If you put it in a pipe line, so that the C library's standard
> > I/O subsystem can't see that stdout is a terminal, like this, where I add
> > cat,
> >
> >   ecashin at atala horkan$ { echo test; sleep 2; echo test; } | ./a.out |
> cat
> >
> > ... then the output doesn't come out as some users might expect---delays
> > are introduced while stdio waits for more output to buffer.  In this
> case,
> > the timestamp appears right away, but its message only appears when the
> > second timestamped message does.
> >
> > You can tell stdio to line-buffer the output and get consistent behavior
> in
> > cases where this matters---i.e., where a human might be watching and
> > wondering, "Where the heck is my output?"  :)
> >
> >   ecashin at atala horkan$ gcc -Wall ts.c
> >   ecashin at atala horkan$ { echo test; sleep 2; echo test; } | ./a.out |
> cat
> >   Thu Nov 14 08:47:23 2013: test
> >   Thu Nov 14 08:47:25 2013: test
> >   ecashin at atala horkan$ diff -u ts.c.orig ts.c
> >   --- ts.c.orig   2013-11-14 08:44:08.000000000 -0500
> >   +++ ts.c        2013-11-14 08:47:15.000000000 -0500
> >   @@ -48,6 +48,8 @@
> >       int ch;
> >       int lastch;
> >
> >   +   setlinebuf(stdout);
> >   +
> >       /* the ctime() man page says ctime is asctime(localtime(&t)) */
> >       /* the localtime() man page suggests calling tzset before using
> > localtime(),
> >          if you want to be portable */
> >   @@ -72,4 +74,6 @@
> >          lastch = ch;
> >
> >       }
> >   +
> >   +   return 0;
> >    }
> >   ecashin at atala horkan$
> >
> > I could swear that many years ago, that (setvbuf stuff) didn't work for
> me
> > on Linux, but who knows.
> >
> > On Wed, Nov 13, 2013 at 7:43 AM, Horkan Smith <ale at horkan.net> wrote:
> >
> > > While I was procrastinating on something else....
> > >
> > > -----begin-----
> > >
> > > /* add_timestamp.c */
> > > /* This messy, poorly commented code was authored by Horkan Smith, and
> I
> > > hearby release it into the public domain. No warranties expressed or
> > > implied. */
> > >
> > > /* Copy stdin to stdout, printing the current time at the start of each
> > > line. */
> > >
> > > #include <stdio.h>
> > > #include <stdlib.h>
> > > #include <string.h>
> > > #include <time.h>
> > >
> > >
> > > /* dump the current time to 'outstream' using 'ctime()' format w/out
> > > newline */
> > > void showtime (FILE *outstream) {
> > >
> > >    time_t t;
> > >    char *p;
> > >    int len;
> > >
> > >    /* current time */
> > >    t = time(NULL);
> > >
> > >    /* shouldn't ever happen w/ a NULL ptr arg, but it doesn't hurt. */
> > >    if ( ((time_t) -1) == t ) {
> > >      perror("\ntime(NULL)");
> > >      exit(-1);
> > >    }
> > >
> > >    /* return a pointer to a string version of current time */
> > >    /* note: not thread safe - use ctime_r() if you use threads! */
> > >    p = ctime(&t);
> > >
> > >    /* We've got to get rid of the newline at the end */
> > >    len = strlen(p) -1;
> > >
> > >    if ((len >= 0) && (*(p + len) == '\n')) {
> > >       *(p + len) = (char) 0;
> > >    }
> > >
> > >    /* could use printf, but sometimes it'll link smaller this way. */
> > >    fputs(p, outstream); fputc(':', outstream); fputc(' ', outstream);
> > >
> > > }
> > >
> > > int main (int argc, char *argv[], char *envp[]) {
> > >
> > >    FILE *instream = stdin;
> > >    FILE *outstream = stdout;
> > >    int ch;
> > >    int lastch;
> > >
> > >    /* the ctime() man page says ctime is asctime(localtime(&t)) */
> > >    /* the localtime() man page suggests calling tzset before using
> > > localtime(),
> > >       if you want to be portable */
> > >    tzset();
> > >
> > >
> > >    /* main loop,
> > >          get a char
> > >          if the last one was a newline, write the timestamp
> > >          write the char out
> > >     */
> > >
> > >    lastch = '\n';
> > >    while (EOF != (ch = fgetc(instream))) {
> > >
> > >       if ('\n' == lastch) {
> > >          showtime(outstream);
> > >          fflush(outstream);
> > >       }
> > >
> > >       fputc(ch, outstream);
> > >       lastch = ch;
> > >
> > >    }
> > > }
> > >
> > > ------end------
> > >
> > > On Tue, Nov 12, 2013 at 01:34:22PM -0500, Scott Plante wrote:
> > > > Does anyone happen to know of a command line tool that will read
> lines
> > > from standard input and write them to std out, pre-pending a
> timestamp? I
> > > have a process that emits messages to std out periodically as it
> processes
> > > and I'd like to write that to a log file, but with a time at the start
> of
> > > the line. I could do it with a script but a nice little command would
> be
> > > better, if it exists.
> > > >
> > > >
> > > > I'm looking for something that would perform the function of this
> > > script, maybe with an option for format:
> > > >
> > > >
> > > > while read line;
> > > > do
> > > > echo $(date +"%D %T") "$line";
> > > > done
> > > >
> > > >
> > > >
> > > > Scott
> > >
> > > > _______________________________________________
> > > > Ale mailing list
> > > > Ale at ale.org
> > > > http://mail.ale.org/mailman/listinfo/ale
> > > > See JOBS, ANNOUNCE and SCHOOLS lists at
> > > > http://mail.ale.org/mailman/listinfo
> > >
> > >
> > > --
> > > Horkan Smith
> > > 678-777-3263 cell, ale at horkan.net
> > > _______________________________________________
> > > Ale mailing list
> > > Ale at ale.org
> > > http://mail.ale.org/mailman/listinfo/ale
> > > See JOBS, ANNOUNCE and SCHOOLS lists at
> > > http://mail.ale.org/mailman/listinfo
> > >
> >
> >
> >
> > --
> >   Ed Cashin <ecashin at noserose.net>
> >   http://noserose.net/e/
> >   http://www.coraid.com/
>
> > _______________________________________________
> > Ale mailing list
> > Ale at ale.org
> > http://mail.ale.org/mailman/listinfo/ale
> > See JOBS, ANNOUNCE and SCHOOLS lists at
> > http://mail.ale.org/mailman/listinfo
>
>
> --
> Horkan Smith
> 678-777-3263 cell, ale at horkan.net
> _______________________________________________
> Ale mailing list
> Ale at ale.org
> http://mail.ale.org/mailman/listinfo/ale
> See JOBS, ANNOUNCE and SCHOOLS lists at
> http://mail.ale.org/mailman/listinfo
>



-- 
  Ed Cashin <ecashin at noserose.net>
  http://noserose.net/e/
  http://www.coraid.com/
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.ale.org/pipermail/ale/attachments/20131114/1f6e2a6a/attachment.html>


More information about the Ale mailing list