iMisspell has asked for the wisdom of the Perl Monks concerning the following question:

Hello all...

I have a script (to decompress files) on my local server which i'll ssh to and run (from a local desktop). While running the script via ssh i can see the state of how its working and read the 'print' commands i have in it.

That same script can also be run via 'cgi' from my home apache server (passing the path to the file which needs to be decompressed via url string).

While running the script via 'cgi' (local web server) i can not read any of the 'print' out-put in-till the script is completly finished.

Question
Is there a way to 'print' the out-put of the script while its running in 'cgi', in "real-time" just like it is being run via ssh/terminal window (and not effect how it is currently working in ssh) ?

The reason for running the script via my web server is i do not want to login to the server all the time. I have a second script in the desktops 'nautilus-scripts' folder which lets me "right-click" on a file that is mapped to a shared folder on the server and send the filename off to my browsers url.
I want all the work being done on the decompressed files to take place on the server, i do not want any of the work load to be done on the desktop.

Server = Ubuntu 10.04x
Perl = v5.10.1 (*) built for x86_64-linux-gnu-thread-multi
Apache = 2.2.14 (Ubuntu)

Thanks for any guidance.

  • Comment on 'print' to cgi like in terminal ("real-time") ?

Replies are listed 'Best First'.
Re: 'print' to cgi like in terminal ("real-time") ?
by zentara (Cardinal) on Jun 28, 2012 at 20:14 UTC
Re: 'print' to cgi like in terminal ("real-time") ?
by tobyink (Canon) on Jun 29, 2012 at 08:23 UTC

    That's not the way the web works. Conceptually, web pages are served up whole. Most web browsers do actually render pages incrementally, showing the start of a page while the end is still downloading; but they don't do so consistently enough to be able to rely on this behaviour for your purposes.

    That said, your desired end result can be achieved. It's just not simple, is likely to require a lot of rewriting for your script, and is probably more effort than it's worth. So you shouldn't bother.

    Here's a general outline of how you'd do it. I'm not going to elaborate any further, and any requests for elaboration only go to prove that you'd ignored my overall advice not to bother!

    First, split the script into two different parts:

    • Workhorse: a command-line script which accepts a filename, and does the actual work while logging all progress to that file (make sure it's unbuffered output).
    • Reporter: a lightweight CGI script that accepts a filename, reads from the file and formats it for display in the browser, and uses either a meta refresh tag or some Javascript to reload itself every couple of seconds.

    Then create another CGI script, which when visited does the following:

    1. Invents a random temporary filename. (Data::UUID or similar is useful for this.)
    2. Spawns the Workhorse as a background process, asking it to log to the temporary file.
    3. Redirects to the Reporter, asking it to report on the temporary file.

    Note I've consistently said filename, not file path. The filename should not include a directory portion. All the scripts should be hard-coded to read from a particular directory set aside for just this purpose. And your Reporter and Workhorse should validate that the filename they receive doesn't contain slashes or "..". This should prevent people using your Reporter to peek at other files on your system that you don't want them to have access to.

    You probably also want to run a cron job on the server to mop up any temporary files older than, say, two hours. And if you know your Workhorse occasionally goes into an endless loop or otherwise spins off out of control, then you may also want a cron job to detect runaway horses and kill them.

    If you were using a server environment with some persistence for Perl processes (e.g. mod_perl) instead of CGI, then this would be somewhat easier.

    perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
      Thanks for the links everyone - will check them out soon.
      Tobyink
      "If you were using a server environment with some persistence for Perl processes (e.g. mod_perl) instead of CGI, then this would be somewhat easier."

      I would be interested in what you have to say about using 'mod_perl':
      Ive toyed with different programing languages (both interpreted and complied), but dont have a strong backround with apache.

      Heres alittle more info about my server. When the time comes i need something or try something new, i enable it - dont know if this is alitle/too much info or not enough.

      Apache/2.2.14 (Ubuntu) DAV/2 SVN/1.6.6 PHP/5.3.2-1ubuntu4.17 with Suhosin-Patch mod_python/3.3.1 Python/2.6.5 mod_ssl/2.2.14 OpenSSL/0.9.8k mod_wsgi/2.8 mod_perl/2.0.4 Perl/v5.10.1 configured --

      $ apache2ctl -M Loaded Modules: core_module (static) log_config_module (static) logio_module (static) mpm_prefork_module (static) http_module (static) so_module (static) alias_module (shared) auth_basic_module (shared) authn_file_module (shared) authz_default_module (shared) authz_groupfile_module (shared) authz_host_module (shared) authz_user_module (shared) autoindex_module (shared) cgi_module (shared) dav_module (shared) dav_fs_module (shared) dav_svn_module (shared) authz_svn_module (shared) deflate_module (shared) dir_module (shared) env_module (shared) mime_module (shared) negotiation_module (shared) -> perl_module (shared) php5_module (shared) python_module (shared) reqtimeout_module (shared) rewrite_module (shared) setenvif_module (shared) ssl_module (shared) status_module (shared) wsgi_module (shared) Syntax OK
      Some info displayed under '/perl-status' ...
      ( /etc/apache2/conf.d/perl-status ) <Location /perl-status> SetHandler perl-script PerlHandler +Apache2::Status </Location> ModPerl::Const 2.000004 Wed Feb 3 13:16:37 2010 /usr/lib/perl +5/ModPerl/Const.pm ModPerl::Global 2.000004 Wed Feb 3 13:16:21 2010 /usr/lib/per +l5/ModPerl/Global.pm ModPerl::Registry 1.99 Wed Feb 3 13:16:48 2010 /usr/lib/perl5 +/ModPerl/Registry.pm ModPerl::RegistryCooker 1.99 Wed Feb 3 13:16:46 2010 /usr/lib +/perl5/ModPerl/RegistryCooker.pm ModPerl::Util 2.000004 Wed Feb 3 13:16:45 2010 /usr/lib/perl5 +/ModPerl/Util.pm mod_perl2 2.000004 Thu Apr 17 02:07:31 2008 /usr/lib/perl5/mo +d_perl2.pm
      This is all for a local server, security is not a big issue (server is not open to public), but i would like to practice safty.

      Thanks again all.
      _