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

Hello wise monks,

I come here seeking wisdom as to why backticks (I know, only use them if I have to) are not playing nicely with my script when it is run through the web. If I run my script through a terminal, it works beautifully, but when I try to run it remotely from a web server it barely does anything.

So the reason I am using backticks is I am automating testing of my script, and I want to know what the result of each run of my script is (what STDERR and STDOUT is generated). As far as I know, backticks are the best way to go about this (correct me if I am wrong though).

This is the code I am using to test my script:

`dashboard.pl --source $_ 1>&2`;

Yes, the path is relative. This is because both the scripts are in the same directory. I have also tried giving the absolute path (/u/alexandg/web/dashboard.pl) and it also was to no avail. The "--source $_" is the argument I use to pass in the test case. I am 100% sure this is not the issue.

The trouble is when I run this same command from the web server, nothing is reported back to the script. Granted I am not checking the return of the backticks, because I want them to ALWAYS continue no matter what happens. If the script I am testing crashes, thats OK, just report it and move onto the next test case.

All of these cases are stored inside of a while loop, and I am iterating over <$FILE> for test cases.

The questions I have are why doesn't this work from the web server, and how can I get it to function from both the command line and from the web?

Thank you!

Replies are listed 'Best First'.
Re: CGI and Backticks
by GrandFather (Saint) on Aug 29, 2011 at 22:20 UTC

    Most likely the credentials of the user running the CGI script are wrong for running the test script. Take a look in the server's log files for errors that look like permissions issues. It may help too to use:

    use CGI::Carp qw(fatalsToBrowser warningsToBrowser);

    to get errors and warnings delivered to your browser. The warnings appear in comments in the HTML.

    True laziness is hard work

      Forgot to mention that Carp is enabled. If it matters STDOUT and STDERR are redirected to the output file using IO::Handle. Similar to CGI Script backgrounding, I fork a child and a parent and have the parent redirect to the child's page where the child's STDOUT/STDERR are redirected to.

      I didn't think any of this should matter so I didn't include this in the question as this logic works BEAUTIFULLY in dashboard.pl itself. (Again, see CGI Script backgrounding for an explanation if you are curious about what dashboard.pl does).

Re: CGI and Backticks
by NetWallah (Canon) on Aug 29, 2011 at 23:35 UTC
    Shouldn't that be "2>&1" , not "1>&2" ?

    Your case streams all output to the second file handle (STDERR). I believe backticks collect only from the first handle (STDOUT).

                "XML is like violence: if it doesn't solve your problem, use more."

Re: CGI and Backticks
by Anonymous Monk on Aug 29, 2011 at 23:57 UTC
    nothing is reported back to the script.

    This is a bit vague. Can you show a bit more of the context in which the backticks are used? What is the value of $? immediately after the backticks expression is run?

    You don't say what your web server is. Some record output to STDERR in their error logs, others discard it. If you are using one of the ones that saves it, you can see what the output of your script was by checking your error logs.

    When I am running a CGI script on a web server that doesn't do what I want with STDERR I redirect it myself, to a file that I can review to find out what happened.

      As to the 1>&2, I'm not sure why it works, but it works the way that I've posted it. I know its backwards, I'm just running with it for right now.

      As to the problem; I've sort of fixed it. Hopefully this won't be overly confusing, but basically I have my test script which is calling a script that forks a child and has the parent return BEFORE the child. Odd, I know, but for reasons I won't get into here, it has to be that way.

      I played around with things, and it turns out that in dashboard.pl, I have the child process redirect its STDOUT and STDERR to a file and this was masking them, but ONLY from the web, not from a terminal. Either way, I have a flag now that the test script passes which overwrites this redirect. Again, not the best solution but it works for now.

      The error logs cannot be obtained from my web server unfortunately, as I am merely one of many, many users on it. I want both STDERR and STDOUT to report back to my script.

      I should probably make a new thread for this, but does anyone know how to see if a child process has finished? I know I can check the pid of the parent, but how do I get the child's? My problem is now that the test script is waiting for the backticks to finish, and when dashboard's parent exits BEFORE the child does, the test script moves on to the next test case, and the previous child's output (STDOUT and STDERR) are getting jumbled with the next test's outputs.

      Thanks in advance for the help, and sorry if you found this wordy/confusing.

        There are several ways you can get both STDERR and STDOUT from a sub-process. perlipc covers some of them. There are also various process management modules available from CPAN that you might consider.

        You can use kill to check whether a process is running or not, but you would need the process ID for that - you could add it to the output of dashboard.pl.

        You may be able to use waitpid to wait for all processes in the process group to finish, if your system supports this.