tags:

views:

224

answers:

9

I'm sure someone could answer this very quickly, but I'm just new to perl...

I'm trying to modify demarc (a simple network monitoring tool) to do a system call to a simple script. The script itself does nothing, I'm just trying to do a 'proof-of-concept' because I keep getting an internal server error. Permissions to the script have been set to 777. When I comment the system() call, everything's fine. So that makes me suspect that it's the system() call where the error's happening. I've also tried exec(), but that didn't work also. The error could not be in the script itself since there's only an echo "test" in it.

Have I missed any permissions or is there some other way of making this work? Any advise would be appreciated.

sub generate_ticket {
   my @args = ("$base_path/test.pl");
   exec(@args);
}

This is called somewhere in file like this:

} elsif ($FORM{'delete_type'}=~/generate/) {
 my $message = &generate_ticket($delete_array_ref);
 #&ack_events($delete_array_ref);
 $events_deleted = (@$delete_array_ref);
 &push_message("<FONT COLOR=red><B>Result: $message.</B></FONT>");
}

test.pl:

#!/usr/bin/perl
print "Test";

Error log: [Mon Nov 30 14:58:22 2009] [error] [client 127.0.0.1] Premature end of script headers: demarc, referer: http://localhost/dm/demarc?td=show%5Fevents&amp;limit=60&amp;sid=35

A: 

It sounds like you want to capture the output from test.pl. Using system or exec will not achieve that (and with exec, your main script will no longer be running by the time test.pl is run).

Instead, you could use backticks:

my $message = `$base_path/test.pl`;
Chris Jester-Young
Well... not really right now, but yes, I'll want to capture it in the future. Right now, I just want it to get over the internal server error.. I'll try the backtick right now....
Ed Gl
This actually works, I'll use this as the last resort.
Ed Gl
If this works, and system doesn't, is it possible somewhere you have a wrong path?
Geo
I don't see how, I outputted the base path to make sure it was in the right directory. I think I now see what's happening. When I run the exec(@args) without assigning the output, that's when the error happens. However, when I assign it:my $output = exec(@args), then I'm OK. granted the output does not contain anything, but could it be that using exec(@args) causes something to be flushed out directly into the http response buffer, and thus it fails. I'll fool around with it some more....
Ed Gl
+2  A: 

You probably want system, not exec:

The exec function executes a system command and never returns-- use system instead of exec if you want it to return.

See the documentation for exec.

Leonardo Herrera
I tried system() first before trying exec(), but it didn't work also... :)
Ed Gl
`system` would at least not-work *differently* in a way that would shine more light on the problem. `exec` is definitively wrong.
hobbs
@hobss: I see. Thanks for the tip.
Ed Gl
A: 

See 500 Server Error in the Perl FAQ list.

You have made sure the script runs from the command line, right?

Sinan Ünür
Yes... I tested this first...
Ed Gl
+2  A: 

Well I guess the first thing you have to do is check your web server log, it usually has a reason to throw an internal server error.

kemp
Checked it, posted it as part of my question. :)
Ed Gl
A: 

It's best that you try a simpler version of what you're trying to do.

Try this:

  • Create something like test2.pl which does something simpler.
  • Run a simplified script.

    #!/bin/perl 
    use feature 'say';
    use strict;
    use warnings;
    use Data::Dumper;
    use English qw<$OS_ERROR>;
    
    
    my $rc = system( "$base_path/test2.pl" );
    say "\$rc=$rc";
    say $OS_ERROR;
    

Now,

  1. If $rc is 0. Then it worked to execute the script that way. Otherwise, $OS_ERROR should tell you.
  2. If this all works, then you could try to execute the original script and see if that works as well.
  3. If that works, then it could be the state of the program at the time it is called.

But, as other people have noted, unless you're all done running the script, exec-ing from the script is not what you want to do, even if it were a program. That would just load the program over the space used by the script.

Using the qx or backticks (\) will allow the command line to be interpreted by the shell which will handle the shebangs (#!`) in the perl script and return the output of the script.

Axeman
A: 

I've always been a fan of using qx for my system calls:

my @array = qx(ls -1);

system returns a string which then needs to be parsed, by qx returns an array, and if you know line 4 has the info you need, you can just go there and grab it.

MikeEL
`system` doesn't return a string, it returns an integer return value and doesn't capture the program's output at all. `qx` returns either a list of lines *or* a string depending on context.
hobbs
Can you point to some documentation that lists qx outputting string/array depending on context? I have never seen that behavior
MikeEL
+3  A: 

"Premature end of script headers" is not a terribly useful error message on its own. It could be caused by any of a number of things, such as:

  • not being executable (permissions problem)
  • failing compilation (syntax error, dependency problem, etc.)
  • terminating prematurely during regular execution
  • producing something other than proper HTTP headers as your script's first output

However, in this case, if we are to take your example script literally (print "TEST"), and you output this before your HTTP headers, then you are not producing HTTP headers first, so it's the last one. The web server expects headers, not "TEST."

If that's not the case, we need to see more of the context of your code to know what might have happened. Could be a permissions problem executing test.pl, for example.

Adam Bellaire
A: 

It's not the Perl CGI which complains, but Apache. Apache says your CGI script is not outputting the required headers so that's the first thing you need to achieve.

I always try CGI with a printenv script first, e.g.

#!/usr/bin/env perl

use warnings;
use strict;

print "Content-type: text/plain\r\n\r\n";
print "$_ => $ENV{$_}\r\n" for sort keys %ENV;

Once that works, try something else.

reinierpost
+1  A: 

One way to find the cause of the premature-thing is to make the errors go to the browser. You just have to send the content-type header early in the application, for example like this, somewhere at the top of your code:

BEGIN {
    print "Content-type: text/plain\n\n";
}

Now you should be able to see the error in the browser.

zoul