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

Hi all. I am running a perl backup script like thus:
$prog = "/usr/sbin/ufsdump"; # dump program $level = "0uf"; # level of dump $part = "/webdocs"; #partition to dump $dev = "/dev/rmt/0un"; #device to dump to $blah = `$prog $level $dev $part`;
$blah returns nothing. The dump runs fine, but the output from the dump does not fill $blah. whereas I do a:
@ls = `ls -la`;
@ls will contain all lines returned by ls -la!

What have I overlooked with my dump, I have tried:
@blah = `$prog $level $dev $part`;
but alas, still no luck. Is there a better way to do it?

Edit kudra, 2002-01-10 Replaced BR with CODE

Replies are listed 'Best First'.
Re: System Calls with backticks
by cat2014 (Monk) on Jan 07, 2002 at 08:35 UTC
    Well, I don't know anything about dump, so this is a random guess. I belive that backticks only catch standard output, not errors or warnings- you have to explicitly capture those. Is it possible that the dump output is really put out on STDERR?

    Also, there are lots of ways to run system commands besides backticks. Check out exec or system-- one of them should work for you.

    -- cat

Re: System Calls with backticks
by MZSanford (Curate) on Jan 07, 2002 at 14:35 UTC
    cat2014 susspected correct. I ran the following test on my machine (Solaris 7) :

    /usr/sbin/ufsdump 0uf /bar /foo
    i got output, and aborted with Ctrl+C

    Then, i tried the following :
    /usr/sbin/ufsdump 0uf /bar /foo 2> stderr.out
    Nothing printed to screen, aborted with Ctrl+C

    This proves that ufsdump writes to STDERR, not STDOUT. There are two fixes.
    1. You could add 2>&1 to the end of your command line. This would re-direct STDERR into STDOUT, and the backticks would work.
    2. You could fork off a child, and re-open STDERR to point to STDOUT, then exec the process. A bit longer method, but does not require the use of a shell (which is non-portable ... not that ufsdump for Win32 is really there.)

    $ perl -e 'do() || ! do() ;' Undefined subroutine &main::try

      There is another option, one which was brought up in the Chatterbox recently. The IPC::Open3 module will automate much of option 2; but is more complex than option 1.

      The choice is essentially between ease of implementation and need to keep stdout separate from stderr. Since stdout seems to be completely empty in this case, I would choose option 1, which is also the easiest to implement.

Re: System Calls with backticks
by Juerd (Abbot) on Jan 07, 2002 at 14:24 UTC
    qx// (also known as backticks) grab only stdout. If the program you're using outputs everything to stderr, qx// will return an empty string (or empty list) accordingly.

    You can use shell redirects to redirect 2 (stderr) to 1 (stdout).
    @foo = `bar 2>&1`

    2;0 juerd@ouranos:~$ perl -e'undef christmas' Segmentation fault 2;139 juerd@ouranos:~$

Re: System Calls with backticks
by jlongino (Parson) on Jan 07, 2002 at 10:11 UTC
    Although TIMTOWTDI, I suspect you'll find that using a shell script of some sort would be easier than using Perl for this purpose. Here is an example of a cshell script which could be scheduled to run as a cron job:
    #! /usr/bin/csh echo -n "** New Backup Job" >> /home/root/tape.log echo -n "** Rewinding tape . . . " >> /home/root/tape.log mt -f /dev/rmt/0 rew echo "**" >> /home/root/tape.log echo "** TAPE #1 Backup begins ("`date '+%Y/%m/%d %H:%M'`") **" >> / +home/root/tape.log echo " " >> /home/root/tape.log echo " Backing up -> /root" >> /home/root/tape.log ufsdump 0uf /dev/rmt/0n /dev/md/dsk/d20 >> & /home/root/tape.log echo " Root finished backing up ("`date '+%Y/%m/%d %H:%M'`")" >> /h +ome/root/tape.log echo -n "** Rewinding/Unloading tape . . . " >> /home/root/tape.log mt -f /dev/rmt/0 rewoffl
    Please be sure to note that this is a very simple example with absolutely no error checking. You should also check out the man pages for additional requirements when using ufsdump (file systems should be inactive, run in single user mode, etc.). A more robust solution using cshell script and Perl (with error checking) can be found here. HTH.

    --Jim