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

Lets say I have a simple perl script that uses backticks, like such:
#!/usr/bin/perl -w $hostname = `hostname`; if ($!) { print "found error of: $!\n"; } else { print $hostname }
The script returns "Bad file descriptor", not the hostname. This seems to be the case anytime I use backticks to run any system command (such as date). Ideas on what I'm doing wrong? Thanks!

Replies are listed 'Best First'.
Re: Bad file descriptor when using backticks?
by Fletch (Bishop) on Feb 13, 2008 at 22:36 UTC

    Erm, backticks don't set $!; they set $?.

    $ perl -le '`bad_command`;print $?;`echo`;print $?' -1 0

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

Re: Bad file descriptor when using backticks?
by Joost (Canon) on Feb 13, 2008 at 22:40 UTC
    Checking $! for errors is never a good idea unless you're sure the last syscall produced an error. $! may have any kind of value if the last syscall did not produce an error or is not documented to set $!.

    As far as I can see the only way to check for this case is to see if the `` operator returned undef:

    my $hostname = `hostname`; unless (defined $hostname) { print "found error of: $!\n"; }
    update: as Fletch mentioned, `` does not set $! but $? so this code doesn't really work.

    In addendum: be aware that not all functions that actually set $! are documented as doing so in the man pages. The only source that I know that seems to mention all of them is the Camel book.

      Your answer was better before the update. qx() can set $! if there was a failure in the parent process. But qx() does always set $? and you need to look at $? in order to figure out if $! was also set. Despite not finding this in the documentation at the moment, I believe that $? being -1 means that $! should be checked / reported.

      - tye        

Re: Bad file descriptor when using backticks?
by starbolin (Hermit) on Feb 14, 2008 at 00:11 UTC

    If I'm doing quick and dirty scrips then I just shell using backticks and don't worry much about the commands not running. If I start to worry about errors then it's time to find a way to do it using perl calls. For your sample in this instance Sys::Hostname is available as a core module and has fallback and error reporting.

    <slings-and-arrrows-off>Actually, as a confession, if the problem is going to need a large proportion of shell builtins then I just code in Bash.<slings-and-arrows-on> <\p>


    s//----->\t/;$~="JAPH";s//\r<$~~/;{s|~$~-|-~$~|||s |-$~~|$~~-|||s,<$~~,<~$~,,s,~$~>,$~~>,, $|=1,select$,,$,,$,,1e-1;print;redo}