Limbic~Region has asked for the wisdom of the Perl Monks concerning the following question:

All:
A vendor provided CGI generates a web page that refreshes itself every 15 seconds or so. They also provide a shell script that is put in the cron to update the data pool as often as you like.

I am guessing the reason that they do not have the page automatically update the data pool itself is because there can only one be one copy of the external shell script running at any one time. The shell script checks to see if it is already running and it aborts if so. This could get complicated if multiple people are viewing the same web page. I know that the vendor COULD have figured out how to handle this, but the bottom line is they didn't.

I would like to change how often the external shell script runs in cron to only once or twice an hour since this web page doesn't get used very much. The problem is, when we do view it - there is the potential the data is a half hour old. My proposed solution is to add a button to the top of the page that says "Update", which would be a hook to call the external shell script - an update on demand if you will.

I know there is still a chance that two people will click the button at the exact same time - but it is reduced dramatically - especially considering we don't use it that often.

Since I am completely CGI illiterate and the vendor says, though I have permission to modify the code, they may choose to update at any time - how do I:

  • Add the button
  • Have it execute the external script
  • Wait until it is finished and then refresh the page
  • Change the code/page as LITTLE as possible

    Waiting for the external script to finish is not absolutely critical since the page refreshes every 15 seconds and it will be updated as soon as the script is finished anyway.

    Any/all help will be appreciated! - L~R

    • Comment on CGI Question - run external script and then update page
  • Replies are listed 'Best First'.
    •Re: CGI Question - run external script and then update page
    by merlyn (Sage) on Feb 06, 2003 at 01:00 UTC
    Re: CGI Question - run external script and then update page
    by tachyon (Chancellor) on Feb 06, 2003 at 01:30 UTC

      On the HTML side you will need a form and submit button to run the update script.

      <form method="POST" action="http://somesite.com/cgi-bin/script.pl"> <input type="Submit" value="Update"> </form> # for the script #!/usr/bin/perl -w use CGI; use Fcntl qw(O_WRONLY O_CREAT O_EXCL); my $q = new CGI; my $lockfile = '/tmp/lock'; if (sysopen(FH, $lockfile, O_WRONLY | O_CREAT | O_EXCL)) { # sysopen will only work if lockfile does not exist # exec the script and wait for it to complete using bacticks or ex +ec `your_update_script`; close FH; unlink $lockfile or error("<h3>Can't unlink lockfile $lockfile $!< +h3>"); print $q->redirect('http://page_to_display_after_update'); } else { error("<h3>Update already in progress!</h3>"); exit; } sub error { print $q->header, shift; }

      Note that there will be collisions with your cron job unless you write a similar short lockfile script and exec that from cron like:

      #!/usr/bin/perl -w use Fcntl qw(O_WRONLY O_CREAT O_EXCL); my $lockfile = '/tmp/lock'; if (sysopen(FH, $lockfile, O_WRONLY | O_CREAT | O_EXCL)) { `your_update_script`; close FH; unlink $lockfile or die "Can't unlink lockfile $lockfile $!"; print "Updated"; } else { die "Update already in progress. Aborting!"; }

      cheers

      tachyon

      s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

    Re: CGI Question - run external script and then update page
    by bart (Canon) on Feb 06, 2003 at 11:05 UTC
      The impression I get from your description here is different from what I got out of our conversation on the ChatterBox. For one, you never said you had access to the source of the CGI script you want to change the output from. I assumed that that page came from the outside world. So it's an entirely different kettle of fish, now.

      Anyway, I've given this some thought, and I must say that your solution seems a bit, er, user-unfriendly. I would think of a more sofisticated solution, completely automatic, and more deeply entwined with the original script. That might pose some problems on the collaboration level with your vendor, because the easy solution to do that, would be to modify the original script.

      What I would attempt, is to let the running of the data fetching script be triggered by the loading of that page. In order for it to be efficient, you'll have to tweak the whole system a little. For example, you might not want this script to run more than once every five minutes or so, depending on how long a run takes, and how resource-hungry it is. So it would need to leave a timestamp mark of the "last run" somewhere, and your launcher script could check that before even firing it up. Another valid test could be to check first if any new data has come in. If not, you can skip the run entirely. This means the system has to be tweaked to set a flag (or a timestamp marker) everytime new data does come in. I think you get the picture by now...

      How can you make this as unobstrusive as possible? If your script runs on the same machine as the original CGI script, just start up the external script with a system() call, or with one of the more elaborate (double) fork schemes, exec, etc. in the CGI script.

      If it doesn't run on the same machine, make your launcher script a CGI script that outputs a 1-pixel transparent GIF (just copy the contents of such an image to STDOUT — with an appropriate content-type header, of course), and place that image in the HTML page. It's a trick web that stat counters often use.

      --
      bart

    Re: CGI Question - run external script and then update page
    by Aristotle (Chancellor) on Feb 06, 2003 at 12:44 UTC
      The brute force solution that does not even touch your initial script at all: write your own CGI script using LWP to proxy requests to the real script, then have the proxy transparently run updates if necessary. It does add significant overhead, but if your traffic is really that low that's not a concern anyway. Any updates to the vendor CGI don't affect you in the least either.

      Makeshifts last the longest.