[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