bret.foreman has asked for the wisdom of the Perl Monks concerning the following question:

I'm making a call to an external program (gnuplot) using the backtick method. As in:
my $output = `gnuplot $cmd`;
The problem is that gnuplot isn't doing what I expect (it's supposed to create a file) and $output is empty. This is running inside a cgi so the user is apache and I suspect some sort of permissions or path problem. I am looking for some sort of message like "command not found" from the system. There might also be buffered stdout from gnuplot telling me of a problem but I'm not getting it. Is there something more I need to do to get those messages?

Thanks,
Bret

Replies are listed 'Best First'.
Re: ticked off with backticks
by aquarium (Curate) on Aug 19, 2004 at 03:51 UTC
    alternatively, use the OPEN function with a pipe like so
    open(GNUPLOT,"gnuplot $cmd |") or die; @output = <GNUPLOT>; close GNUPLOT or die "error reading GNUPLOT";
    this is my preferred way. The close function makes sure that buffers are flushed. From my experience as programmer...the complex lines in a program are usually not at fault...instead it's the simple lines that cause problems. print $cmd to stdout just to make sure it has what you think it has. regarding apache user permissions...you can replicate how it works on the webserver by su - nobody, or whatever the apache user is, and try to run the program on the command line, i.e. gnuplot $whatever_your_cmd_is
      Since IPC::Run was not installed on my system, I tried the open method first. The close of GNUPLOT fails and $! is empty. I guess it's failing because I'm trying to close it with some data still buffered but why no error message?

      I also put some invalid options in the gnuplot command to be sure that it is returning an error message. But @output is empty. The message is probably still buffered in GNUPLOT. Is there a way to flush it?

      Thanks,
      Bret

        The message is probably still buffered in GNUPLOT. Is there a way to flush it?

        The call to <GNUPLOT> in list context will slurp everything the filehandle has to read, and close should flush any buffers automatically. With aquarium's code, if the buffers fail to flush, die would be called.

Re: ticked off with backticks
by BUU (Prior) on Aug 19, 2004 at 00:20 UTC
    or die "$!:$?";
Re: ticked off with backticks
by etcshadow (Priest) on Aug 19, 2004 at 03:05 UTC
    my $output = `gnuplot $cmd 2>&1`;
    That will merge the STDERR output of gnuplot into STDOUT, so it'll all end up together in $output. Then you go from there in terms of working out your issues.

    BTW, you might have better luck using IPC::Run, if you need to separate STDOUT and STDERR:

    use IPC::Run qw( run ); my ($stdout, $stderr); run ["gnuplot", $cmd], undef, \$stdout, \$stderr;
    Something like that.
    ------------ :Wq Not an editor command: Wq
Re: ticked off with backticks
by naChoZ (Curate) on Aug 19, 2004 at 04:10 UTC
Re: ticked off with backticks
by revdiablo (Prior) on Aug 19, 2004 at 16:27 UTC
    This is running inside a cgi

    Excuse the slightly off-topic post, but I hope your $cmd variable isn't coming from user input. Or, if it is, I hope you're scrubbing it well. If not, you have opened yourself up to a major security hole. Fortunately, it's pretty easy to solve. Here's an adapted version of aquarium's solution:

    open(GNUPLOT, "-|", gnuplot => $cmd) or die; @output = <GNUPLOT>; close GNUPLOT or die "error reading GNUPLOT";

    Since this uses the list form of open, the shell is never called. This eliminates the possibility of shell metacharacters being interpreted by your backtick command.

      No no. The $cmd stuff is all internally generated in the CGI. The user just selects stuff from scrolling lists.

      Bret

        Generating $cmd inside the CGI is good, and your code may indeed be safe (hard to judge without seeing the actual code), but using dropdown lists does not help. Users can make their web clients submit anything they want, really.

Re: ticked off with backticks
by Nkuvu (Priest) on Aug 19, 2004 at 05:56 UTC
    Given that this is a CGI, have you looked at Apache's error logs to see if there's helpful information in there?