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

I am writing a simple script that mounts a disk and checks to see if it did it right.

So far I have this:

my $device = "/dev/cdrom"; my $dir = "/mnt/cdrom"; my $testfile = ""; print `mount $device $dir`; if ($?) { if ( -f "$dir/$testfile" ) { print "mounted." } else { print "There was an error in mounting $device at $dir. +\n" } } else { print "mounted\n" }

This works, but I would like more info about the error. I thought that doing something like this:

$output = `mount $device $dir`;

would get me what's being displayed to the screen (eg. "..mounted read only..", "only root can do that", etc.), but alas I was mistaken.

Anyone know of a good way to do that?

thanks.

melguin.

Replies are listed 'Best First'.
Re: getting output from backticks
by bikeNomad (Priest) on Jul 19, 2001 at 03:05 UTC
    Re-direct the standard error output and read that:

    my $errFile = 'mount.err'; my $stdout = qx("mount $device $dir 2>&1"); if ($?) { printf "mount error code ", $?>>8, " $stdout"; }

    The 2>&1 directs the stderr to the same place as the stdout.

Re: getting output from backticks
by buckaduck (Chaplain) on Jul 19, 2001 at 03:10 UTC
    I haven't used it myself, but the module IPC::Open3 will let you do this and more. You'll have to create filehandles for STDIN, STDOUT, and STDERR. You should be able to read the error message from the STDERR handle.

    buckaduck

Re: getting output from backticks
by MZSanford (Curate) on Jul 19, 2001 at 15:14 UTC
    Well, the things already put forward are more that adequate for fixing this one problem, simply by using system() and checking the return code. But, in the interest of edjucating everyone, including myself, i will cover how to read the output of the command (which was the question, although the reason was a bit flawed):

    Reading Command Outout: To execute a command and read the output from it, a simple way is to use the open() command. This is usually needed when you want to run an external program and parse it's output (stdout to the program). This is commonly used as :
    open(MNT,"mount $device $dir |") || die "Could not run mount : $!\ +n";
    but, sometimes you need both the STDOUT and STDERR from a program. While not the most portable way, the following works on Unix systems :
    open(MNT,"mount $device $dir 2>&1 |") || die "Could not run mount +: $!\n";
    Once again, the return code from mount will cover what you need, but if you were running, say, ps, you may need to parse it. See also open.
    OH, a sarcasm detector, that’s really useful
(jeffa) Re: getting output from backticks
by jeffa (Bishop) on Jul 19, 2001 at 02:48 UTC
    You should try system - unlike backticks, it does not gather the executed program's STDOUT, but unlike backticks, it does gather the program's exit value and stores it in $?

    UPDATE: listen to bikeNomad - STDERR is your friend here :)

    Jeff

    R-R-R--R-R-R--R-R-R--R-R-R--R-R-R--
    L-L--L-L--L-L--L-L--L-L--L-L--L-L--
    
      I have tried that, but got exactly the same results: $? is 0 before the call. After the call it is 256 if there was an error and 0 if there wasn't.

      Thanks though. Any other ideas? From what I've read in the documentation and from previous questions on this site, that sould be right.

      conan.

        Well the 256 result code should track back to a more specific error - if you check out the documentation for mount - you may find out more precisely what that error means.

        As for system Vs. backticks etc. - when I have to use one or the other - I generally try this sub:
        # SubRoutine: sysrun # # Run System Command sub sysrun { my ($command) =@_; my $ret_code; $ret_code = system("$command"); if ( $ret_code == 0 ) { # Job suceeded $ret_code = 1; } else { # Job Failed $ret_code = 0; } return ($ret_code); }
        While this doesn't store the return code from the system call, it does allow you to treat the system call with logical operators like any other perl program

        Also, the return_code can easily be logged if there is an error from this sub.
        game(Wookie,opponent) eq 'Wookie' ? undef $problem : remove_limbs(arms,opponent);
Re: getting output from backticks
by jlongino (Parson) on Jul 19, 2001 at 20:47 UTC
    To expound further on the virtues of "system" check out Programming Perl for documentation of the system function. There is a code snippet for interpreting various possibilities including signals and coredumps on a UNIX system. I used the snippet and made a subroutine called sysub:
    function sysub { my $cmd = shift; my $rc = 0xffff & system $cmd; if ($rc == 0xffff) { print "command failed: $!\n"; } elsif ($rc > 0x80) { $rc >>= 8; print "ran with nonzero exit status $rc\n"; } elsif ($rc != 0) { print "ran with "; if ($rc & 0x80) { $rc &= ~0x80; print "coredump from "; } print "signal $rc\n"; } return ($rc != 0); }
    a sample invocation:
    &sysub ("cp $source $target");
    Unfortunately, I never researched the reasoning behind all the bit-twiddling but it has served me well for several years. I would appreciate enlightenment from more advanced monks on this aspect of the code. Also, any suggestions or improvements would be welcomed.