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

Fellow Monks--

I have a (huge) maintenance script that is designed to run with command line parameters, and I'm trying to design an interface which will allow you to trigger the script from an HTML form, as an alternative to having to do it through a Unix command line or cron job.

So, I wrote a CGI script in Perl that contains a system call to the maintenance script, grabs the return code and prints it to the browser. Well, the maintenance script isn't executing, and system returns -1. The code looked something like this (CGI and print junk omitted):

... my $output = system "perl product_gen.pl -rfpv"; ...
I thought it should work, but it doesn't. I tried replacing the system call with backticks, to no avail. The ultimate end goal would be to capture the maintenance script's output, and print that to the browser, but I'd settle for just getting the bugger to run!

As always, many thanks in advance for any assistance!

  higle

Replies are listed 'Best First'.
Re: Executing another script from a CGI
by derby (Abbot) on Jul 24, 2002 at 19:55 UTC
    Sound like a path problem. Remember, your web scripts probably run as a different user (nobody) who may or may not have the same path as you. Try using fullpaths and using the '-w' flag:

    my $output = system "/path/to/perl -w /path/to/script -opts";

    -derby

      Thanks!

      Wow, I didn't even think to check that. I thought we had our box configured with Perl in the path for CGI processes, but I guess not.

      My philosophy has always been, "Check the simplest things first." Looks like I should follow my own advice...

        higle
        ...correct me if I'm wrong, but you still may have a problem.

        Supplying the full path will get this additional script to run, but I don't think you're going to get the output from the command by grabbing the return value from system().

        What you'll get stored in $output will simply be the exit code from your other script.

        So here's how you can execute the external script and grab the output into a variable:

        open (PROC "/path/to/perl myscript.pl |") || die "horribly"; @lines = <PROC>; close PROC;

        You may want to add other civilities, such as join()'ing the lines of output into one big scalar if that suits you. But this is one good way of grabbing output from a running process. Best of luck.

        ---v

Re: Executing another script from a CGI
by sauoq (Abbot) on Jul 25, 2002 at 02:12 UTC

    If you really want the output, you might want to go back to using backticks. You can get the return code from $? after the command has run and you can capture or print the output.

    Also, keep in mind that the return code, both as returned by system() and as available in $? is actually the value returned by the wait() system call. You will need to shift it to the right by 8 bits (or divide by 256) to get the actual return code.

    Something like this:

    #!/usr/bin/perl # This is minimal and hasn't been checked at all. print "Content-type: text/html\n\n"; print `/path/to/perl -w /path/to/script -opts`; # FIX THIS LINE print "Exit value: ", $? >> 8;
    -sauoq
    "My two cents aren't worth a dime.";
    
Re: Executing another script from a CGI
by Ryszard (Priest) on Jul 25, 2002 at 10:35 UTC
    Things like this can be a little "interesting" from a security p.o.v.

    Have you considered forking off a child process to run the external script then validating the output doesnt contain anything naughty?

    As an optional extra you could embed a checksum in the cgi, then verify the checksum against the external script. Its far from water tight, but if you secure the cgi, you can give yourself some indication there has been an unauthorised change to the external script.