motionblurrr has asked for the wisdom of the Perl Monks concerning the following question:

This is probably simple, but I'm not getting anywhere. What I'm actually trying to do in my script is more complex, but I've simplified my code into the following to isolate the issue. Take a look at this simple script:
#!/usr/bin/perl $res = `echo test`; print $res; print $! . "\n";'
The output to the shell is as follows:
test Bad file descriptor
So, what I don't understand is why $! is "Bad file descriptor"? I can choose not to check $! and my script runs fine... but I'm obsessing over why it would present an error at all.

Also, I'm not using system() because I need the data from STDOUT. Any help is appreciated! Thanks!

Replies are listed 'Best First'.
Re: Using backquotes to echo results in "Bad file descriptor"
by ELISHEVA (Prior) on Mar 04, 2009 at 18:40 UTC

    Although this is not cause of the "Bad File Descriptor" message, a small observation about your sample code: it is a good idea to get in the practice of assigning things like $! (os error), $? (child error) and $@ (thrown exception) $^E (extended OS error) and so on to a variable immediately after the call that generates them. If you are not watchful, the code to process them can accidentally reset them.

    The practice of assigning them straight away to a named variable prevents this and many a wild goose chase looking for bugs.

    Best, beth

      As in like this?:
      #!/usr/bin/perl $res = `echo test`; print $! . "\n";' print $res;
      Good point, thanks.
Re: Using backquotes to echo results in "Bad file descriptor"
by kennethk (Abbot) on Mar 04, 2009 at 18:15 UTC
    From the perlvar entry for $!:
    A successful system or library call does not set the variable to zero.
    A read through of error indicators will likely be illuminating.
      I'm completely fine with not using $! as an error indicator. I also understand that an earlier system/library call could have set it since it doesn't get reset, but you'll notice there are no other commands in my example, so I know that's not the case.

      I just did another test using a different shell command (ls) and $! produces the same thing. So my guess is that $! gets set to "Bad file descriptor" whenever you use backquotes that send data to STDOUT. If I redirect to /dev/null $! is empty.

      I appreciate the help, but I'm not trying to simply "get my script working", I'm trying to understand why $! gets set. Call it curiosity. I call it OCD. ;)
        Did you read error indicators? Essentially (as gwadej and toolic as also pointed out) you are not checking the error code you think you are. $! is set by the perl C libraries, not by external system calls, and its value is essentially meaningless unless a Perl library call (like open) just failed. On the other hand $? is set to the return value of the invoked system call, and as such is what you need to check in the case of backticks (or system).
Re: Using backquotes to echo results in "Bad file descriptor"
by gwadej (Chaplain) on Mar 04, 2009 at 18:16 UTC

    The var $! refers to the C library errno global variable. It is set in many places in the runtime system. errno is not explicitly reset by any library function.

    You should only check $! if you know there is an error. (Such as after a failed open.) In fact, perlvar specifically states that it is meaningless if an error has not occurred.

    In this case, you probably want $? which contains the error generated by the backticks operator.

    G. Wade
Re: Using backquotes to echo results in "Bad file descriptor"
by toolic (Bishop) on Mar 04, 2009 at 18:17 UTC