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

Hey guys, I have a pretty big script that makes a lot of print calls at various points to generate an html output -- is there anyway I can have the output save to the server automatically each time this is ran? If this was a more simple script I could just push the print statements to "whatever > /dir/name.html" but in this case that's not really an option.

I thought about making a system call to run the script again at the end, however I'm not sure if this is able to be done due to the nature of the input which is a file (users go to an .html front end page and then select the file to upload which is used for the script input). I tried something like:

system("perl /dir/script.cgi parametername='/dir/file' > /dir/output.html");

However the output html file I get just gives me my invalid file message so it doesn't look like it takes the input in that way. Is there a better way to approach this or should I be able to pass a file as a parameter in the system perl call?

Replies are listed 'Best First'.
Re: Saving .cgi Output; Passing File As Argument?
by MidLifeXis (Monsignor) on Oct 20, 2014 at 17:49 UTC

    Are the results different if the user-supplied parameters are different? Perhaps you could use a proxy front-end module from your web server to provide this function. I believe that Apache mod_rewrite has an example of this for automatically generating files in a cache.

    Alternatively, you could save the output, before sending it to the client, as a file based on some unique, per-request generated file name. Do not base the file name on any unsanitized data, or it could become an avenue for exploitation.

    A third option might be to store the response text in a blob field in a database.

    Each option has benefits and drawbacks, but without further information, it is difficult to even recommend an approach to take.

    --MidLifeXis

      Thanks for the reply, the users upload a .dat file which gets extracted and parsed and the script spits out a bunch of information based on the content. Since they do have to upload files to the server and it has to be extracted, I have the files uploaded and named based on a sequential counter so that each are unique and I know how many of times it's been used (I have the script delete the files at the end of the script)--the trouble is I don't know how to save the output at all other than brute-force doubling every print statement and pushing it to a file.

        How about, instead of printing at every step, collecting the data to print, and then printing to both locations destinations in a single location?

        Update: minor wording change

        --MidLifeXis

Re: Saving .cgi Output; Passing File As Argument?
by thewebsi (Scribe) on Oct 20, 2014 at 19:37 UTC
    I'm not sure if this is able to be done due to the nature of the input which is a file ... I tried something like: ... However the output html file I get just gives me my invalid file message so it doesn't look like it takes the input in that way.

    The input is not a file, but an HTTP request. The HTTP request content includes the file embedded in it.

    As you are suggesting running the script again using the command-line, this might be the simplest approach. Most (Plack-based) modern Perl web frameworks provide a command-line tool for doing this, so if you are using one of those, then check the documentation for it. For generic web servers such as a LAMP setup, you can use wget, curl, or lwp-download. Check the documentation on those for how to POST a request with a file attached. Windows has similar tools available. Watch out for recursion if you do this!

    To avoid running the script twice, a more generic approach is to use a filter/handler. Again, this depends on the web framework, as any framework that buffers output can make this very easy to do. For Apache, check out: http://httpd.apache.org/docs/current/handler.html#examples

Re: Saving .cgi Output; Passing File As Argument?
by Loops (Curate) on Oct 20, 2014 at 19:03 UTC

    Would something like File::Tee or even the following work?

    open (STDOUT, "| tee -ai log.txt");