2

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.

Derek N
  • 33
  • 3
  • It sounds like an association problem. You need to fix the file association, or not rely on a file association (e.g. by using `system("start perl C:/path/to/script/test2.pl");`, possibly with the full path to `perl.exe`) – ikegami Oct 06 '19 at 16:57

3 Answers3

1

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.

Schwern
  • 153,029
  • 25
  • 195
  • 336
  • `start foo` is to `cmd` what `foo &` is to `sh`. The `start` still needs to be included because the OP doesn't want to wait for the child to end. – ikegami Oct 06 '19 at 17:56
  • I wouldn't recommend `fork` on a Windows machine. – ikegami Oct 06 '19 at 17:57
  • This does not work as I described above - the CGI script waits for the test2.pl to complete before returning. This needs to run in the background. The CGI script should not be waiting for test2.pl to finish. Thank you for the input. I did at least get it to run, although not how I need it to. – Derek N Oct 06 '19 at 18:01
  • I currently have `system('start C:/path/to/perl/perl.exe C:/path/to/script/test2.pl')` in place, but it is causing the browser to still wait until test2.pl is complete before returning. I'm not sure what you mean by "not having an association set up between .pl files and perl executable"...my web server is configured to handle any .cgi or .pl files using interpreter at C:/path/to/perl/perl.exe. I don't know what else this could entail? – Derek N Oct 06 '19 at 18:44
  • Re "*but it is causing the browser to still wait until test2.pl is complete*", That's a problem unrelated to the one you asked about. Ask a new question. – ikegami Oct 06 '19 at 19:04
  • Incorrect and not helpful at all. Please re-read the original post. Quote: "...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..." – Derek N Oct 06 '19 at 19:34
1

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.

Derek N
  • 33
  • 3
-1

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.

Holli
  • 5,072
  • 10
  • 27