zsh-users
 help / color / mirror / code / Atom feed
* piping stderr
@ 2009-05-14 10:49 Atom Smasher
  2009-05-14 16:04 ` Bart Schaefer
  0 siblings, 1 reply; 8+ messages in thread
From: Atom Smasher @ 2009-05-14 10:49 UTC (permalink / raw)
  To: zsh-users

i'd like to pipe all stderr from a script into a command to do logging... 
but this isn't synchronous:
 	exec 2> >( multilog /path/ )

i need it to be synchronous so that multiple scripts running at the same 
time (and also logging debug messages) can all log together and not 
clobber each others output.

is it possible to do what i'm trying?

thanks...


-- 
         ...atom

  ________________________
  http://atom.smasher.org/
  762A 3B98 A3C3 96C9 C6B7 582A B88D 52E4 D9F5 7808
  -------------------------------------------------

 	"America may be the best country in the world, but that's
 	 kind of like being the valedictorian of summer school."
 		-- Dennis Miller


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: piping stderr
  2009-05-14 10:49 piping stderr Atom Smasher
@ 2009-05-14 16:04 ` Bart Schaefer
  2009-05-15 11:47   ` Atom Smasher
  0 siblings, 1 reply; 8+ messages in thread
From: Bart Schaefer @ 2009-05-14 16:04 UTC (permalink / raw)
  To: zsh-users

On Thu, May 14, 2009 at 3:49 AM, Atom Smasher <atom@smasher.org> wrote:
> i'd like to pipe all stderr from a script into a command to do logging...
> but this isn't synchronous:
>        exec 2> >( multilog /path/ )
>
> i need it to be synchronous so that multiple scripts running at the same
> time (and also logging debug messages) can all log together and not clobber
> each others output.

I'm not sure what you think "synchronous" implies here.  Within a
particular "instance" of zsh, such as a single running script,
commands can be synchronous in the sense that zsh waits for the
command to finish before going on to the next one.  However, multiple
scripts "running at the same time" already implies that the zsh
instances are asynchronous with respect to one another, so no command
started by a particular zsh instance will be synchronous with respect
to other instances (unless you employ some sort of external locking
scheme, but then you're just preventing the scripts from "running at
the same time").

That said ... have you tried your example above?  I'd be mildly
surprised if multilog doesn't already do something to assure that
multiple loggers don't clobber one another's output.  They might
intermingle their output, in which case you need to tag each line of
it with a PID or some such, but Dan Bernstein is generally pretty
compulsive about preventing data loss.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: piping stderr
  2009-05-14 16:04 ` Bart Schaefer
@ 2009-05-15 11:47   ` Atom Smasher
  2009-05-15 21:00     ` Kurtis Rader
  0 siblings, 1 reply; 8+ messages in thread
From: Atom Smasher @ 2009-05-15 11:47 UTC (permalink / raw)
  To: zsh-users

On Thu, 14 May 2009, Bart Schaefer wrote:

> On Thu, May 14, 2009 at 3:49 AM, Atom Smasher <atom@smasher.org> wrote:
>> i'd like to pipe all stderr from a script into a command to do logging...
>> but this isn't synchronous:
>>        exec 2> >( multilog /path/ )
>>
>> i need it to be synchronous so that multiple scripts running at the 
>> same time (and also logging debug messages) can all log together and 
>> not clobber each others output.
>
> I'm not sure what you think "synchronous" implies here.  Within a 
> particular "instance" of zsh, such as a single running script, commands 
> can be synchronous in the sense that zsh waits for the command to finish 
> before going on to the next one.  However, multiple scripts "running at 
> the same time" already implies that the zsh instances are asynchronous 
> with respect to one another, so no command started by a particular zsh 
> instance will be synchronous with respect to other instances (unless you 
> employ some sort of external locking scheme, but then you're just 
> preventing the scripts from "running at the same time").
==============

among different scripts (different invocations of the same script) things 
are wildly asynchronous. but within each script, which is logging debug 
output into multilog, i want to make sure that the stderr and debug 
messages appear in the right order. this script shows how that doesn't 
(always) happen:

  #!/bin/zsh

  exec 2> >(rot13)

  date
  dattxxx
  date
  dattxxx
  date
  dattxxx
  date
  dattxxx

the "dattxxx" commands are there to produce "command not found" errors on 
stderr. with zsh 4.2.1 the redirect into a coproc makes it just hang.


> That said ... have you tried your example above?  I'd be mildly 
> surprised if multilog doesn't already do something to assure that 
> multiple loggers don't clobber one another's output.  They might 
> intermingle their output, in which case you need to tag each line of it 
> with a PID or some such, but Dan Bernstein is generally pretty 
> compulsive about preventing data loss.
============

if there's one thing multilog does, it makes sure that multiple inputs 
don't clobber each other. i am tagging each line with a PID so i can grep 
out a particular process and see what's going on.

the problem i'm seeing with the script above, and variations on it, is 
that sometimes the output is in the right order, but sometimes all of 
stdout appears, followed by all of stderr.


-- 
         ...atom

  ________________________
  http://atom.smasher.org/
  762A 3B98 A3C3 96C9 C6B7 582A B88D 52E4 D9F5 7808
  -------------------------------------------------

 	"HEY! HO! LET'S GO!"
 		-- The Ramones


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: piping stderr
  2009-05-15 11:47   ` Atom Smasher
@ 2009-05-15 21:00     ` Kurtis Rader
  2009-05-16  0:25       ` coloring stderr - was " Atom Smasher
  0 siblings, 1 reply; 8+ messages in thread
From: Kurtis Rader @ 2009-05-15 21:00 UTC (permalink / raw)
  To: Atom Smasher; +Cc: zsh-users

The behavior you're seeing is due to how the Unix stdio library buffers 
output. The stderr stream is always line buffered by default. When the 
file descriptor is open on a tty both stdout is line buffered. When 
directed to a pipe, fifo, or file stdout is fully buffered. Which means 
that when you redirect the output to a file or a coprocess (which sends 
the output through a pipe) the stderr output will typically be seen 
first because it is flushed as soon as an entire line is written. But 
even that isn't guaranteed since if the program writes a large amount of 
data to stdout some or all of the data could be flushed before the first 
line is written to stderr. The only reliable way to solve this is to 
redirect the output to a pty (psuedo-tty). One way is to use the 
script(1) command to run your script and capture its output.

On 09-05-15 04:47, Atom Smasher wrote:
> On Thu, 14 May 2009, Bart Schaefer wrote:
>
>> On Thu, May 14, 2009 at 3:49 AM, Atom Smasher <atom@smasher.org> wrote:
>>> i'd like to pipe all stderr from a script into a command to do
>>> logging...
>>> but this isn't synchronous:
>>> exec 2> >( multilog /path/ )
>>>
>>> i need it to be synchronous so that multiple scripts running at the
>>> same time (and also logging debug messages) can all log together and
>>> not clobber each others output.
>>
>> I'm not sure what you think "synchronous" implies here. Within a
>> particular "instance" of zsh, such as a single running script,
>> commands can be synchronous in the sense that zsh waits for the
>> command to finish before going on to the next one. However, multiple
>> scripts "running at the same time" already implies that the zsh
>> instances are asynchronous with respect to one another, so no command
>> started by a particular zsh instance will be synchronous with respect
>> to other instances (unless you employ some sort of external locking
>> scheme, but then you're just preventing the scripts from "running at
>> the same time").
> ==============
>
> among different scripts (different invocations of the same script)
> things are wildly asynchronous. but within each script, which is logging
> debug output into multilog, i want to make sure that the stderr and
> debug messages appear in the right order. this script shows how that
> doesn't (always) happen:
>
> #!/bin/zsh
>
> exec 2> >(rot13)
>
> date
> dattxxx
> date
> dattxxx
> date
> dattxxx
> date
> dattxxx
>
> the "dattxxx" commands are there to produce "command not found" errors
> on stderr. with zsh 4.2.1 the redirect into a coproc makes it just hang.
>
>
>> That said ... have you tried your example above? I'd be mildly
>> surprised if multilog doesn't already do something to assure that
>> multiple loggers don't clobber one another's output. They might
>> intermingle their output, in which case you need to tag each line of
>> it with a PID or some such, but Dan Bernstein is generally pretty
>> compulsive about preventing data loss.
> ============
>
> if there's one thing multilog does, it makes sure that multiple inputs
> don't clobber each other. i am tagging each line with a PID so i can
> grep out a particular process and see what's going on.
>
> the problem i'm seeing with the script above, and variations on it, is
> that sometimes the output is in the right order, but sometimes all of
> stdout appears, followed by all of stderr.
>
>


^ permalink raw reply	[flat|nested] 8+ messages in thread

* coloring stderr - was Re: piping stderr
  2009-05-15 21:00     ` Kurtis Rader
@ 2009-05-16  0:25       ` Atom Smasher
  2009-05-16  0:47         ` Atom Smasher
  2009-05-18  0:40         ` Vincent Lefevre
  0 siblings, 2 replies; 8+ messages in thread
From: Atom Smasher @ 2009-05-16  0:25 UTC (permalink / raw)
  To: zsh-users

this has me thinking about an old problem... coloring stderr. the two 
problems i've found previously are (1) keeping stdout and stderr in sync, 
and (2) stderr that doesn't end with a newline, such as messages from "rm 
-i".

this [below] fixes the second problem, but it's still got some unintended 
consequences... the problem i'm having now with it is that if i start bash 
as a child of zsh, bash is a bit messed up. if i start a bourne shell 
(which doesn't actually exist on most/all linux distros, so don't bother 
testing it there) i can see that PS1 is going through stderr, as it's 
being piped the zsh's "color_err" function. if i start a few levels of zsh 
children all with this function, i'm not even sure i want to know how ugly 
things are under the hood. of course all children of the process will have 
their stderr going through this, but with interactive applications that 
can result in some weird stuff...

## colorize std_err
zmodload zsh/terminfo zsh/system
autoload colors is-at-least
if [[ "${terminfo[colors]}" -ge 8 ]] { colors }
color_err () {
   ## sysread & syswrite are part of zsh/system
    while sysread std_err_color
    do
      syswrite -o 2 "${fg_bold[red]}${std_err_color}${terminfo[sgr0]}"
    done
}
## i'm not sure exactly how far back it's safe to go with this
## 4.3.4 works; 4.2.1 hangs.
is-at-least 4.3.4 && exec 2> >( color_err )


-- 
         ...atom

  ________________________
  http://atom.smasher.org/
  762A 3B98 A3C3 96C9 C6B7 582A B88D 52E4 D9F5 7808
  -------------------------------------------------

 	"I believe that banking institutions are more dangerous
 	 to our liberties than standing armies."
 		-- Thomas Jefferson


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: coloring stderr - was Re: piping stderr
  2009-05-16  0:25       ` coloring stderr - was " Atom Smasher
@ 2009-05-16  0:47         ` Atom Smasher
  2009-05-18  0:40         ` Vincent Lefevre
  1 sibling, 0 replies; 8+ messages in thread
From: Atom Smasher @ 2009-05-16  0:47 UTC (permalink / raw)
  To: zsh-users

http://smasher.org/tmp/snapshot152.png

another unintended consequence of redirecting stderr in an interactive 
shell... note that "cal" is actually "gcal".


-- 
         ...atom

  ________________________
  http://atom.smasher.org/
  762A 3B98 A3C3 96C9 C6B7 582A B88D 52E4 D9F5 7808
  -------------------------------------------------

 	"It is well enough that people of the nation do not
 	 understand our banking and monetary system, for if
 	 they did, I believe there would be a revolution before
 	 tomorrow morning."
 		-- Henry Ford


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: coloring stderr - was Re: piping stderr
  2009-05-16  0:25       ` coloring stderr - was " Atom Smasher
  2009-05-16  0:47         ` Atom Smasher
@ 2009-05-18  0:40         ` Vincent Lefevre
  2009-05-18  6:09           ` Atom Smasher
  1 sibling, 1 reply; 8+ messages in thread
From: Vincent Lefevre @ 2009-05-18  0:40 UTC (permalink / raw)
  To: zsh-users

[-- Attachment #1: Type: text/plain, Size: 1312 bytes --]

On 2009-05-16 12:25:50 +1200, Atom Smasher wrote:
> this has me thinking about an old problem... coloring stderr. the two 
> problems i've found previously are (1) keeping stdout and stderr in sync, 
> and (2) stderr that doesn't end with a newline, such as messages from "rm 
> -i".
> 
> this [below] fixes the second problem,

I also solved the second problem a few years ago (see my solution in C,
attached). But I've checked again... the first problem is not solved by
my solution:

$ echo L1; echo L2 >&2; echo L3; echo L4 >&2
L1
L3
L2
L4

Also I disabled stderr coloring because some programs do not use stderr
consistently and I had various problems with them (perhaps because of
lack of synchronization).

> but it's still got some unintended consequences... the problem i'm
> having now with it is that if i start bash as a child of zsh, bash
> is a bit messed up.

I can notice that the bash prompt doesn't appear, because bash has
not been started in interactive mode ('i' is not in "$-"). If I force
interactive mode, I get:

prunille:~> bash -i
zsh: suspended (tty input)  bash -i

-- 
Vincent Lefèvre <vincent@vinc17.org> - Web: <http://www.vinc17.org/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.org/blog/>
Work: CR INRIA - computer arithmetic / Arenaire project (LIP, ENS-Lyon)

[-- Attachment #2: colorize.c --]
[-- Type: text/plain, Size: 2843 bytes --]

/* $Id: colorize.c 29330 2009-05-18 00:27:09Z vinc17/prunille $
 *
 * Colorize the standard input. Written for zsh stderr coloring.
 *
 * Bug: stdout and stderr are not synchronized. For instance,
 *   $ echo L1; echo L2 >&2; echo L3; echo L4 >&2
 *   L1
 *   L3
 *   L2
 *   L4
 */

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/types.h>

#define BUFFSIZE 512

static volatile sig_atomic_t usr1;

static void sigusr1(int sig)
{
  usr1 = 1;
}

static void writepid(char *tmpfile)
{
  FILE *f;

  f = fopen(tmpfile, "w");
  if (f == NULL)
    {
      perror("colorize (fopen)");
      exit(EXIT_FAILURE);
    }
  fprintf(f, "%ld\n", (long) getpid());
  if (fclose(f) != 0)
    {
      perror("colorize (fclose)");
      exit(EXIT_FAILURE);
    }
}

int main(int argc, char **argv)
{
  pid_t zshpid = 0;
  char *begstr, *endstr;
  fd_set rfds;
  int ret;

  if (argc != 3 && argc != 5)
    {
      fprintf(stderr,
              "Usage: colorize <begstr> <endstr> [ <zshpid> <tmpfile> ]\n");
      exit(EXIT_FAILURE);
    }

  /* Assume that the arguments are correct. Anyway, it is not possible
     to check them entirely. */
  begstr = argv[1];
  endstr = argv[2];
  if (argc == 5)
    {
      /* To do the synchronization with the zsh prompt output...
         Seems to be useless in practice, hence the argc == 3 case. */
      zshpid = atol(argv[3]);
      signal(SIGUSR1, sigusr1);
      writepid(argv[4]);
    }

  fcntl(0, F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK);

  /* To watch stdin (fd 0). */
  FD_ZERO(&rfds);
  FD_SET(0, &rfds);

  for (;;)
    {
      ret = select(1, &rfds, NULL, NULL, NULL);

      if (ret < 0 && errno != EINTR)
        {
          perror("colorize (pselect)");
          exit(EXIT_FAILURE);
        }

      if (ret > 0)
        {
          static unsigned char buffer[BUFFSIZE];
          static int dontcol = 0;
          ssize_t n;

          while ((n = read(0, buffer, BUFFSIZE)) >= 0)
            {
              ssize_t i;

              if (n == 0)
                return 0;  /* stdin has been closed */
              for (i = 0; i < n; i++)
                {
                  if (buffer[i] == 27)
                    dontcol = 1;
                  if (buffer[i] == '\n')
                    dontcol = 0;
                  if (!dontcol)
                    fputs(begstr, stdout);
                  putchar(buffer[i]);
                  if (!dontcol)
                    fputs(endstr, stdout);
                }
            }
          fflush(stdout);
        }

      if (usr1)
        {
          usr1 = 0;
          if (kill(zshpid, SIGUSR1) != 0)
            {
              perror("colorize (kill)");
              exit(EXIT_FAILURE);
            }
        }
    }
}

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: coloring stderr - was Re: piping stderr
  2009-05-18  0:40         ` Vincent Lefevre
@ 2009-05-18  6:09           ` Atom Smasher
  0 siblings, 0 replies; 8+ messages in thread
From: Atom Smasher @ 2009-05-18  6:09 UTC (permalink / raw)
  To: zsh-users

On Mon, 18 May 2009, Vincent Lefevre wrote:

>> but it's still got some unintended consequences... the problem i'm 
>> having now with it is that if i start bash as a child of zsh, bash is a 
>> bit messed up.
>
> I can notice that the bash prompt doesn't appear, because bash has not 
> been started in interactive mode ('i' is not in "$-"). If I force 
> interactive mode, I get:
>
> prunille:~> bash -i
> zsh: suspended (tty input)  bash -i
=================

yeah, that counts as messed up ;)

http://smasher.org/tmp/snapshot153.png

it's not every day that something on the command line dies from SIGTTIN.

back to the drawing board....


-- 
         ...atom

  ________________________
  http://atom.smasher.org/
  762A 3B98 A3C3 96C9 C6B7 582A B88D 52E4 D9F5 7808
  -------------------------------------------------

 	"That's hard to tell. I think that, you know, I would hope
 	 to be able to convince people I could handle the Iraqi
 	 situation better."
 		-- George "dubya" Bush
 		Bush-Gore debate, 11 Oct 2000


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2009-05-18  6:10 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-05-14 10:49 piping stderr Atom Smasher
2009-05-14 16:04 ` Bart Schaefer
2009-05-15 11:47   ` Atom Smasher
2009-05-15 21:00     ` Kurtis Rader
2009-05-16  0:25       ` coloring stderr - was " Atom Smasher
2009-05-16  0:47         ` Atom Smasher
2009-05-18  0:40         ` Vincent Lefevre
2009-05-18  6:09           ` Atom Smasher

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).