in reply to Capturing STDERR with -

I recommend the open(STDERR, ">&STDOUT") solution, unless you really need both channels to be separate, where your script can tell the difference between STDERR output and STDOUT output. I also suggest you add something to your exec line:
exec("/usr/sbin/nslookup", ...) or die "Could not exec: $!"

As it is now, if your exec failed, execution would continue through your script. If this code were in a loop, you would have written yourself a pretty effective fork bomb.

Replies are listed 'Best First'.
Re: Re: Capturing STDERR with -
by DrManhattan (Chaplain) on Dec 06, 2001 at 18:53 UTC
    open(STDERR, ">&STDOUT") was actually the first thing I tried, but I'm afraid it doesn't work. I think the issue is that I'm exec()ing a new process. Open file handles for the perl script go away when the process is replaced.

    -Matt

      Try it again. I modified your 'exec' block to look like this:

      open(STDERR, ">&STDOUT") if $redirect_stderr; exec("/usr/bin/nslookup", "-q=$query_type", $input, $nameserver) or die "exec: $!";

      I also took out the 'splice' and ran your function like this:

      print "Without:\n"; print "| $_\n" foreach nslookup('test', 'A'); print "\n"; $redirect_stderr++; print "With:\n"; print "| $_\n" foreach nslookup('test', 'A');

      My output was this:

      Without: Note: nslookup is deprecated and may be removed from future releases. Consider using the `dig' or `host' programs instead. Run nslookup wit +h the `-sil[ent]' option to prevent this message from appearing. | *** Invalid option: q=A | Server: ns.intranet | Address: 10.0.0.1#53 | | ** server can't find test: NXDOMAIN With: | Note: nslookup is deprecated and may be removed from future release +s. | Consider using the `dig' or `host' programs instead. Run nslookup w +ith | the `-sil[ent]' option to prevent this message from appearing. | *** Invalid option: q=A | Server: ns.intranet | Address: 10.0.0.1#53 | | ** server can't find test: NXDOMAIN

      The 'deprecated' warning is sent out via STDERR, which is being captured in the second run. So it seems to be working perfectly for me.

      Note that even though you're doing an exec, file descriptors 0, 1 and 2 (STDIN, STDOUT and STDERR) are inherited by the child process. (This is configurable with $^F; see perlvar.) Since all you're doing here is 'dup'ing 2 to be the same as 1, all 3 get passed as-is and work as you expect.

      On a lesser note, if it is this warning you're trying to omit, is there any reason you're still coding your script to use 'nslookup' instead of, as it recommends, 'dig' or 'host'? The 'dig' tool is pretty easily parseable and I think intended for applications like this moreso than nslookup was. Just a thought..

        Interesting. What operating system are you using? This doesn't work under Solaris 8. I added the open() statement to my script again and ran this:
        print "OUTPUT: $_" for nslookup("blah.", "A");
        Here's the output:
        *** ns1.coxmail.com can't find blah.: Non-existent host/domain OUTPUT: Server: ns1.coxmail.com OUTPUT: Address: 206.157.231.13 OUTPUT:
        STDERR still goes to my console.

        Regarding the splice, it's to get rid of the three lines you see output there (Server, Address, and a blank). 'host' and 'dig' do not ship with Solaris 8.

        -Matt