Derek N
Derek N

Reputation: 35

How to call asynchronous Perl script from CGI file using system()

Let me preface my question by saying that I HAVE read numerous different posts on SO as well as web searches and have been unable to find anything that fits my exact situation.

The problem is quite simple, actually. I have a CGI script (Perl) serving up dynamic pages on web server, and when a user loads a certain page, I want to have the CGI script call a .pl file using system() to do some "housekeeping". This is running in a Windows NT environment.

The CGI script for testing purposes is test1.pl or test1.cgi, e.g. "https://www.awebsite.com/test1.pl".

test1.pl (cgi script that generates web pages)

#!/usr/bin/perl

print "Content-type: text/html\n\n";

print "Hello user, this is a test page.";

system("start C:/path/to/script/test2.pl");

print "Page is fully loaded and housekeeping is being done, even though this page is now fully loaded";

test2.pl (separate .pl file that is doing "housekeeping", asynchronously from what test1.pl is doing)

#!/usr/bin/perl

#just a counter that takes a while to complete, to verify test2.pl is running
for ($x=0; $x <= 100000; $x++){print "$x ";}

Ok, so keep in mind this is for testing operations, not functionality. When running test1.pl from command line, it works fine.

When running test1.pl from a browser, this keeps prompting "openWith.exe" on the server (viewed in Task Manager). My .pl files are executable, so it's not a matter of an unknown file type or not knowing to run with Perl command line interpreter. I cannot figure out what is going on here and why it will not run the system command from test1.pl when called through web interface.

There are NO parameters being passed from user input. test1.pl simply needs to run test2.pl to do some housekeeping, but I cannot have test1.pl waiting for test2.pl to complete before continuing. So, test2.pl should be started by test1.pl and continue running - meanwhile, test1.pl has already finished doing its thing. I do not need or want to capture any output from test2.pl .

I hope I have explained this clearly. I have used simple examples, even though the actual code will be much more complex. At this point, it's not even running these simple example scripts so the actual functioning code is not important at this time.

Thank you to anyone who can help me. By the way, I tried setting "full control" permissions for test1.pl and this didn't help. Again, this "openwith.exe" is really throwing me for a loop here.

Upvotes: 2

Views: 544

Answers (3)

Derek N
Derek N

Reputation: 35

Finally figured it out (as usual, on my own). Turns out Schwern, you were on the right track. Even though the .pl file association was established through control panel to open with Perl Command Line Interpreter, there was a problem with a windows file type association (blahblahblah that I don't even fully understand). I finally found the answer to the TRUE problem here: Perl not running in Windows 10

In particular, this part here:

You must create a file association between the .pl file extension and the Perl runtime. At a command prompt type the following.
assoc .pl=PerlScript
ftype PerlScript=c:\perl\bin\perl.exe %1 %*

I hope that this helps SOMEONE down the road who might be encountering this same problem.

Upvotes: 1

Holli
Holli

Reputation: 5072

You can stay in the semantics of the environment (cgi/web) and make script2 it's own CGI script, which you then then fire an async http request to in script1. You could use HTTP::Async for this. But then you must take care script2 cannot be called from the outside, e.g. by checking the client ip.

Also, since this is a cgi, script1 can potentially run multiple times in parallel, same goes then for script2, however you end up calling it. So you must make sure you don't mess things up when that happens.

Upvotes: -1

Schwern
Schwern

Reputation: 165110

start C:/path/to/script/test2.pl relies on having an association set up between .pl files and your perl executable. You might have that set up on your user, but the web server might not.

You could set that up. Or you can not use start and instead pass your program to perl directly. How exactly you do this depends on how your Perl is installed and your web server is set up. You might be able to just use perl.exe.

system('perl.exe C:/path/to/script/test2.pl');

Or you might have to pass the full path.

system('C:/path/to/perl.exe C:/path/to/script/test2.pl');

See the documentation for start for more detail.


Note that running Perl programs from Perl programs is less than ideal. There's numerous hard to debug things which can go wrong once you start passing data and checking for errors.

Instead consider making that code a subroutine and using fork or threads to run it in the background. Or better yet, use a web framework such as Dancer and link it to a job queue like Minion.

Upvotes: 1

Related Questions