This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: stdout/stderr handling by cygrunsrv/bash/tcl


On Wed, 3 Mar 2004, Patrick Samson wrote:

> --- Igor Pechtchanski wrote:
> > On Tue, 2 Mar 2004, Patrick Samson wrote:
> >
> > > I run a service installed as:
> > >
> > > cygrunsrv --install pgr-daemon
> > >  --path /usr/bin/bash.exe
> > >  --args "--login /opt/pgreplica/bin/pgrd host1 host2"
> > >  --user pgreplicator
> > >  --shutdown
> > >
> > > Everything is fine with stdout.  Messages are in /var/log/pgr-daemon.log
> > >
> > > But if my application, which is a TCL script, writes something on stderr
> > > (as "puts stderr $msg"),
> > > This message is written:
> > > - at the beginning of the file, overwriting the existing stdout text.
> > > - only when the service is stopped.
> > >
> > > Is it an as-is behaviour, a lack or a mistake in the command syntaxes,
> > > or something wrong in cygrunsrv or bash or tcl?
> >
> > Patrick,
> >
> > WFM.  I can't reproduce your problem on Win2k
> > (without Tcl and --user).
> > Here's what I did:
> >
> > $ mkdir /tmp/servicetest && cd /tmp/servicetest
> > $ cat > service.sh
> > #!/bin/bash
> > terminate() {
> >   echo "Terminating" >&2
> >   exit 0
> > }
> > trap terminate INT
> > echo "Starting service" >&2
> > trap -p
> > while true; do
> >   sleep 10
> >   echo "STDERR" >&2
> >   echo "STDOUT" >&1
> > done
> > $ cygrunsrv --install test-daemon --path /usr/bin/bash.exe --args "--login /tmp/servicetest/service.sh" --termsig INT --shutdown
> > $ cygrunsrv -S test-daemon; sleep 30; cygrunsrv -E test-daemon
> > $ cat /var/log/test-daemon.log
> > Starting service
> > trap -- 'terminate' SIGINT
> > STDERR
> > STDOUT
> > STDERR
> > STDOUT
> > STDERR
> > STDOUT
> > Terminating
> > $
> >
> > So, messages going to stdout/stderr were properly redirected.  If the
> > above works for you, try adding a Tcl call to the test script, and see
> > if it changes anything.
>
> Your demo works as expected. But TCL introduces
> the mess.
>
> I changed the script to:
>
> $ cat service.sh
> #!/bin/bash
> # the next line restart using tclsh \
> exec tclsh "$0" "$@"
>
> puts "Starting service"
> while {true} {
>   # wait 1 sec
>   after 1000
>   puts stderr "STDERR"
>   puts "STDOUT"
> }
> $ cygrunsrv -S test-daemon; sleep 3; cygrunsrv -E
> test-daemon
> $ cat /var/log/test-daemon.log
> STDERR
> STDERR
> STDERR
> STDERR
>
> STDOUT
> STDOUT
>
> It looks like the overwriting of these two lines
> (cr lf are replaced by space):
> STDERR  STDERR  STDERR  STDERR
> Starting service  STDOUT  STDOUT  STDOUT  STDOUT
>
> Just for the understanding, another trial with the
> script beginning with a write to stderr:
>
> $ cat service.sh
> #!/bin/bash
> # the next line restart using tclsh \
> exec tclsh "$0" "$@"
>
> puts stderr "Write stderr"
> puts "Starting service"
> while {true} {
>   # wait 1 sec
>   after 1000
>   puts stderr "STDERR"
>   puts "STDOUT"
> }
> $ cygrunsrv -S test-daemon; sleep 3; cygrunsrv -E
> test-daemon
> $ cat /var/log/test-daemon.log
> Starting serviSTDESTDOSTDESTDOSTDESTDOSTDESTDOUT
>
> Again the overwriting of these two lines:
> Write stderr  STDERR  STDERR  STDERR  STDERR
> Starting service  STDOUT  STDOUT  STDOUT  STDOUT
>
> If I run the TCL directly, it's ok, no surprise:
> $ ./service.sh
> Write stderr
> Starting service
> STDERR
> STDOUT
> STDERR
> STDOUT
> STDERR
> STDOUT
> <manually interruped with ctrl/c>
> $ ./service.sh >service.log 2>&1
> <manually interruped with ctrl/c>
> $ cat service.log
> Write stderr
> Starting service
> STDERR
> STDOUT
> STDERR
> STDOUT
> STDERR
> STDOUT
>
> I wouldn't use this syntax, but it shows the same
> problem, so it may be a clue:
>
> $ ./service.sh >service.log 2>service.log
> <manually interruped with ctrl/c>
> $ cat service.log
> Starting serviSTDESTDOSTDESTDOSTDESTDOUT
>
> Continuing on this way, consider:
> serviceSH.sh as the shell script of Igor,
> serviceTCL.sh as the TCL script.
>
> $ ./serviceSH.sh >service.log 2>service.log
> trap -- 'terminateSTDERR
> STDERR
> Terminating
>
> $ ./serviceSH.sh >>service.log 2>>service.log
>
> Starting service
> trap -- 'terminate' SIGINT
> STDERR
> STDOUT
> STDERR
> STDOUT
> STDERR
> STDOUT
> Terminating
>
> $ ./serviceTCL.sh >service.log 2>service.log
>
> Starting serviSTDESTDOSTDESTDOSTDESTDOUT
>
> $ ./serviceTCL.sh >>service.log 2>>service.log
>
> Starting serviSTDESTDOSTDESTDOSTDESTDOSTDESTDOUT
>
> Can someone tell us how cygrunsrv manages the
> redirections? It's a step toward the explanation.

cygrunsrv redirects each file separately (like the '>>a 2>>a' syntax).
This is obviously a Tcl problem.  It seems that Tcl attempts to manage its
own buffering on STDOUT/STDERR, even when they are redirected.

Try adding an 'exec 2>&1' just before the 'exec tclsh "$0" "$@"' in your
serviceTCL.sh script.  Hopefully, Tcl will inherit the stderr from the
parent process...  If this works, you can add it to your main script,
since you know that both stdout and stderr will eventually go to the same
file anyway.
	Igor
-- 
				http://cs.nyu.edu/~pechtcha/
      |\      _,,,---,,_		pechtcha@cs.nyu.edu
ZZZzz /,`.-'`'    -.  ;-;;,_		igor@watson.ibm.com
     |,4-  ) )-,_. ,\ (  `'-'		Igor Pechtchanski, Ph.D.
    '---''(_/--'  `-'\_) fL	a.k.a JaguaR-R-R-r-r-r-.-.-.  Meow!

"I have since come to realize that being between your mentor and his route
to the bathroom is a major career booster."  -- Patrick Naughton

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]