www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How would I retrieve the stdout error message of a system/shell

reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
E.g.:

import std.process;

void main()
{
    auto res = shell("dmd bla.d");
}

where bla.d doesn't exist. This will throw an exception, but even if I
caught the exception I will still loose the error message. Is there
any way I could grab the error message? In this case it would be:

"std.exception.ErrnoException std\process.d(356):  (No error)"

Okay that's a pretty useless error as it is, but other errors might be
more informative and I'd like to grab them.
Sep 08 2011
next sibling parent reply Justin Whear <justin economicmodeling.com> writes:
The Posix solution is to use pipes. Basically, you'll want the parent 
process to set up a pipe for stderr, fork, then the child process uses the 
write end of the stderr while the parent reads from the other end. Not sure 
what the Windoze solution is.
Alternatively, the cheap and easy way is to use redirects:

system("dmd bla.d 2>error.log");

If an error is thrown, read from error.log.
Sep 08 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 09/08/2011 07:26 PM, Justin Whear wrote:
 The Posix solution is to use pipes. Basically, you'll want the parent
 process to set up a pipe for stderr, fork, then the child process uses the
 write end of the stderr while the parent reads from the other end. Not sure
 what the Windoze solution is.
 Alternatively, the cheap and easy way is to use redirects:

 system("dmd bla.d 2>error.log");

 If an error is thrown, read from error.log.

I think the easiest way on a posix system is this: auto res=shell("dmd bla.d 2>&1"); I haven't tested it tough. What it should do is redirect dmd's stderr to stdout, which can then be read.
Sep 08 2011
parent reply Justin Whear <justin economicmodeling.com> writes:
That'll work if you don't mind normal output being mixed with error 
messages.


Timon Gehr wrote:

 On 09/08/2011 07:26 PM, Justin Whear wrote:
 The Posix solution is to use pipes. Basically, you'll want the parent
 process to set up a pipe for stderr, fork, then the child process uses
 the write end of the stderr while the parent reads from the other end.
 Not sure what the Windoze solution is.
 Alternatively, the cheap and easy way is to use redirects:

 system("dmd bla.d 2>error.log");

 If an error is thrown, read from error.log.

I think the easiest way on a posix system is this: auto res=shell("dmd bla.d 2>&1"); I haven't tested it tough. What it should do is redirect dmd's stderr to stdout, which can then be read.

Sep 08 2011
parent reply travert phare.normalesup.org (Christophe) writes:
Justin Whear , dans le message (digitalmars.D.learn:29380), a écrit :
 That'll work if you don't mind normal output being mixed with error 
 messages.
 
 
 Timon Gehr wrote:
 
 On 09/08/2011 07:26 PM, Justin Whear wrote:
 The Posix solution is to use pipes. Basically, you'll want the parent
 process to set up a pipe for stderr, fork, then the child process uses
 the write end of the stderr while the parent reads from the other end.
 Not sure what the Windoze solution is.
 Alternatively, the cheap and easy way is to use redirects:

 system("dmd bla.d 2>error.log");

 If an error is thrown, read from error.log.

I think the easiest way on a posix system is this: auto res=shell("dmd bla.d 2>&1"); I haven't tested it tough. What it should do is redirect dmd's stderr to stdout, which can then be read.


Well, if shell throws, it will not return, and the output will not be assigned to res.
Sep 08 2011
parent reply Justin Whear <justin economicmodeling.com> writes:
Good point. It looks like shell throws if the return value is an error code 
(something other than 0 on Posix). It looks like dmd does return an error 
code on failed compilation, so redirecting to stdout won't work. Back to the 
pipes or file redirect then.


Christophe wrote:

 Justin Whear , dans le message (digitalmars.D.learn:29380), a écrit :
 That'll work if you don't mind normal output being mixed with error
 messages.
 
 
 Timon Gehr wrote:
 
 On 09/08/2011 07:26 PM, Justin Whear wrote:
 The Posix solution is to use pipes. Basically, you'll want the parent
 process to set up a pipe for stderr, fork, then the child process uses
 the write end of the stderr while the parent reads from the other end.
 Not sure what the Windoze solution is.
 Alternatively, the cheap and easy way is to use redirects:

 system("dmd bla.d 2>error.log");

 If an error is thrown, read from error.log.

I think the easiest way on a posix system is this: auto res=shell("dmd bla.d 2>&1"); I haven't tested it tough. What it should do is redirect dmd's stderr to stdout, which can then be read.


Well, if shell throws, it will not return, and the output will not be assigned to res.

Sep 08 2011
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 09/08/2011 08:21 PM, Justin Whear wrote:
 Good point. It looks like shell throws if the return value is an error code
 (something other than 0 on Posix). It looks like dmd does return an error
 code on failed compilation, so redirecting to stdout won't work. Back to the
 pipes or file redirect then.


 Christophe wrote:

 Justin Whear , dans le message (digitalmars.D.learn:29380), a écrit :
 That'll work if you don't mind normal output being mixed with error
 messages.


 Timon Gehr wrote:

 On 09/08/2011 07:26 PM, Justin Whear wrote:
 The Posix solution is to use pipes. Basically, you'll want the parent
 process to set up a pipe for stderr, fork, then the child process uses
 the write end of the stderr while the parent reads from the other end.
 Not sure what the Windoze solution is.
 Alternatively, the cheap and easy way is to use redirects:

 system("dmd bla.d 2>error.log");

 If an error is thrown, read from error.log.

I think the easiest way on a posix system is this: auto res=shell("dmd bla.d 2>&1"); I haven't tested it tough. What it should do is redirect dmd's stderr to stdout, which can then be read.


Well, if shell throws, it will not return, and the output will not be assigned to res.


It seems DMD actually writes the error messages to stdout anyways. This will stop shell from throwing: auto res = shell("dmd bla.d | cat");
Sep 08 2011
prev sibling next sibling parent Justin Whear <justin economicmodeling.com> writes:
For posterity's sake, the "correct" (and much more complicated way) is to 
use pipes and fork(). Here's a Posix-only implementation I wrote a while 
ago: http://pastebin.com/CBYw4fDU

No guarantees on the code, but it demonstrates how to set up the pipes, etc. 
The cool thing is that it supports full two-way communication--the parent 
process can write to the child's stdin and read from both stdout and stderr.

Cheers,
Justin
Sep 08 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 08 Sep 2011 14:14:40 -0400, Justin Whear  
<justin economicmodeling.com> wrote:

 For posterity's sake, the "correct" (and much more complicated way) is to
 use pipes and fork(). Here's a Posix-only implementation I wrote a while
 ago: http://pastebin.com/CBYw4fDU

 No guarantees on the code, but it demonstrates how to set up the pipes,  
 etc.
 The cool thing is that it supports full two-way communication--the parent
 process can write to the child's stdin and read from both stdout and  
 stderr.

This is the plan for the revamped version of std.process, which is held up waiting for DMC changes. -Steve
Sep 08 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 9/8/11, Steven Schveighoffer <schveiguy yahoo.com> wrote:
 This is the plan for the revamped version of std.process, which is held up
 waiting for DMC changes.

That's good news, thanks. I'll try the various pipe/redirect methods soon.
Sep 08 2011
prev sibling parent "Regan Heath" <regan netmail.co.nz> writes:
On Thu, 08 Sep 2011 16:33:49 +0100, Andrej Mitrovic  
<andrej.mitrovich gmail.com> wrote:
 E.g.:

 import std.process;

 void main()
 {
     auto res = shell("dmd bla.d");
 }

 where bla.d doesn't exist. This will throw an exception, but even if I
 caught the exception I will still loose the error message. Is there
 any way I could grab the error message? In this case it would be:

 "std.exception.ErrnoException std\process.d(356):  (No error)"

 Okay that's a pretty useless error as it is, but other errors might be
 more informative and I'd like to grab them.

I have, somewhere, a windows (or perhaps cross platform?) pipestream/subprocess implementation. But, this was for an older version of D/phobos and may not now compile. I'll have a look for it tonight, or later today (as, hopefully we'll have internet at home this afternoon). -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Sep 09 2011