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

Ok,

I'm still trying to figure out have to run a program in unix from a cgi script. First I wrote a simple program that printed "hi" in a text file then read the text file and printed it out in html. Then I made it so that `ls` was executed, put in the file and then read and printed out. I did this to be sure I was on the right track. Now I want to run a program called lm. It's a tool which I would like to use to update the status of something. My problem is that in an xterm it works fine but in a browser the lm output never makes it to the file. I suspect it has to do with environment variables but i'm not sure. Here's my test code:

#!/usr/bin/perl $hi = `ls`; `setenv LM_DIR /opt/corp/projects/board_simulation/tools/hw_model-3.4/ +sms/lm_dir`; `setenv LM_LIB /opt/corp/projects/board_simulation/tools/hw_model-3.4/ +sms/models:/opt/corp/projects/board_simulation/tools/hw_model-3.4/sms +/maps`; `setenv VCS_LMC_HM_ARCH sun4.solaris`; `setenv LMC_PATH /opt/corp/projects/board_simulation/lib/custom_swift_ +v41`; $lm = `lm show_modeler -m wmers0c3.1`; $logfile = "lmout.txt"; open (FILE, ">$logfile") or die "I can't open that now\n"; print FILE "hi"; print FILE "$hi"; print FILE "$lm"; close(FILE); open (FILE, "$logfile") or die "I can't open that now\n"; while (<FILE>) { push @Contents, $_; } close(FILE); print "Content-type: text/html\n\n"; print "<html>\n <head>\n <title>lm</title>\n </head>\n\n"; print "<body>\n"; foreach $Content(@Contents){ print "$Content<br>"; } print "\n"; print "</body>\n</html>\n";

Replies are listed 'Best First'.
Re: calling a unix prog
by Fastolfe (Vicar) on Nov 07, 2000 at 02:30 UTC
    `setenv LM_DIR /opt/corp/projects/board_simulation/tools/hw_model-3.4/ +sms/lm_dir`;
    This won't work. By using the back-ticks (or any system-ish command), you are spawning a sub-process and telling it to execute that command. Environment changes only persist at or below the level of the process making them, so after each of these statements, the environment change is lost.

    See How can I change the environment from within my Perl script? in the Q&A section. Modify the contents of %ENV instead to set up your environment, and then execute your programs that rely on that environment.

Re: calling a unix prog
by arturo (Vicar) on Nov 07, 2000 at 02:44 UTC

    I think Fastolfe has the solution to your problem, but I'd just like to emphasize that backticks are rather expensive, as perl goes to a lot of trouble to gather the output of the command it spawns in the subshell. Consider using system instead, and check to see that the calls succeed. system is a little odd, in that it returns 0 (which in Perl, is a false value) on success, so your system calls should look like:

    system("foo") && die "Couldn't execute foo:$!";

    Instead of the usual or die

    Philosophy can be made out of anything. Or less -- Jerry A. Fodor

      As pointed out earlier in some other thread, $! will not provide any helpful message on errors from system() or backticks. You will usually get a system error message which has no relation to $! echoed to STDERR though, and the rest of your die message will print with the line number.
RE: calling a unix prog
by Octavian (Monk) on Nov 07, 2000 at 02:39 UTC
    The problem I run into most often is that when things are being run through a browser, it is running as "www". if you are trying to do something that only specific users can do, like root stuff, it wont work.
RE: calling a unix prog
by extremely (Priest) on Nov 07, 2000 at 05:41 UTC
    Are you saying that this line: $lm = `lm show_modeler -m wmers0c3.1`; is leaving $lm set to "" when you get to the print to file portion of your code? If that is the case is the lm utility you call actually printing to STDERR rather than STDOUT? If so, I'm pretty sure that the backticks won't grab STDERR. You might want to do something like this:
    $lm = `lm show_modeler -m wmers0c3.1 >2&1`; #bash shell

    I have no idea on other shells tho, That part of my brain melted 4 years ago.

    Update: Ouch Fastolfe is correct. Turns out the bash part of my brain melted too. =P

    --
    $you = new YOU;
    honk() if $you->love(perl)

      You probably mean 2>&1.