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