Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options

System commands using CGI

by nikhilB (Initiate)
on Dec 03, 2012 at 06:06 UTC ( #1006794=perlquestion: print w/replies, xml ) Need Help??
nikhilB has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I am trying to execute system commands from CGI but it doesnt work.If I execute the same code from command line, the code works fine.

#!/usr/bin/perl print "content-type: text/html \n\n"; # SET UP THE TABLE print "<table border='1'>"; print "<th>Test</th><th>Value</th><th>Expected Value</th><th>Result</t +h>"; $x=system("who",">>/var/www/cgi-bin/new.txt");

Any help will be greatly apreciated

Replies are listed 'Best First'.
Re: System commands using CGI
by rjt (Deacon) on Dec 03, 2012 at 06:38 UTC

    It's likely that the who program is not in the $PATH of the web server's environment. Try printing out $ENV{PATH} in your CGI program to verify this. Anyway, the more secure route is to specify the full path of the command you want to execute, usually /usr/bin/who or /bin/who (check by running which who from a shell prompt).

    Second, I'm not sure what you intend to do with the text file, but if you intend to show the output inside your CGI program (or even if you don't), you have introduced a race condition by sending the output to the same text file every time. (If two visitors hit the CGI very close together, the first visitor might see the second visitor's who output.) A better way to handle this is to capture the output with qx// or backticks.

    my $output = `/usr/bin/who`; print '<p>Something went horribly awry!</p>' if $?;
      Hi rgt, Thanks for the reply. I tried using the following but it looks like the command doesnt get executed from the CGI :
      #!/usr/bin/perl print "content-type: text/html \n\n"; # SET UP THE TABLE print "<table border='1'>"; print "<th>Test</th><th>Value</th><th>Expected Value</th><th>Result</t +h>"; $b=`/usr/bin/who>>/root/abcd.txt`; print "$array[1]\n\n"; #print "VALUE IS $b\n\n"; print "<tr><td>".$b."</td>";
      When I run this from the command prompt, it the gives the correct output.

      Any idea where I am going wrong ?


        Your code here did not generate that output. It was hard to read without <code> tags, so I reformatted it for you:

        #!/usr/bin/perl print "content-type: text/html \n\n"; # SET UP THE TABLE print ""; print ""; $b=`/usr/bin/who&gt;&gt;/root/abcd.txt`; print "$array<a href="?node=1">1</a>\n\n"; # <== FIXME #print "VALUE IS $b\n\n"; print "";

        Your code here does not compile. You need to escape the double quotes in your print "$array... line.

        Beyond that, however, why in the world are you trying to append the output of /usr/bin/who to /root/abcd.txt? More to the point, please let us know exactly what your CGI program is supposed to do, and perhaps then we can get to the root of the problem (no pun intended... or maybe it was...).

        A webserver with root access? Doubtful

        The lack of code tags that rjt pointed out also munges up the formatting of the replies. It looks like the empty print statements in what he posted contain table related tags, like:

        #!/usr/bin/perl print "content-type: text/html \n\n"; # SET UP THE TABLE print "<table border='1'>"; print "<th>Test</th><th>Value</th><th>Expected Value</th><th>Result</t +h>"; $b=`/usr/bin/who>>/root/abcd.txt`; print "$array<a href="?node=1">1</a>\n\n"; #print "VALUE IS $b\n\n"; print "<tr><td>".$b."</td>";
        It would make it easier to sort out the replies if you can go back and wrap your code in code tags.
Re: System commands using CGI
by ColonelPanic (Friar) on Dec 03, 2012 at 09:07 UTC

    Obligatory standard response:

    use strict; use warnings;

    This will encourage you to write better code, in particular declaring all of your variables as lexical.

    use CGI;

    It is much better to use the CGI module to handle your output, rather than rolling your own. For a discussion of this, see one of the great ancient works of the monastery.

    use CGI::Carp qw/fatalsToBrowser/;

    This enables you to see your script's fatal errors in the browser. Essential for debugging.

    Finally, checking the error given by system would probably be helpful:

    my $err = system("who",">>/var/www/cgi-bin/new.txt"); unless ($err == 0) { die "who command failed: $?"; }

    See the documentation for system for more information on checking the error codes.

    When's the last time you used duct tape on a duct? --Larry Wall
Re: System commands using CGI
by dsheroh (Prior) on Dec 03, 2012 at 10:10 UTC
    Aside from
    use strict; use warnings;
    the next major point for debugging problems in web-related code is to check your web server's error log to find the error message generated when things went wrong.

    In this particular case, I expect that you'll find an "access denied" error indicating that the user the web server runs as (probably "nobody", "apache", "httpd", or "www-data", depending on your OS and distribution) doesn't have permission to create or append to /var/www/cgi-bin/new.txt. The reason it works when you run it from the command line is that you have permission to create and write to that file, but the web server doesn't, so it fails when run by the web server.

    If my guess as to the cause is correct, then the solution is to first create that file from the command line, then give the web server user permission to write to it. Do not give the web server user write permission to the entire /var/www/cgi-bin/ directory, as that would open up huge security holes allowing anyone who compromised one of your cgi-bin scripts to then create their own new scripts (or replace existing ones) on your machine.

    Or, better, tell us what you're actually trying to achieve and we can probably find a way to do it that doesn't require allowing the web server process to write directly to files in potentially-sensitive locations.

      Thanks all for the response. I am trying to run a the perl script from the browser. The perl script is supposed to run some system level commands and print on the webpage. I figured out that the changes needed in the httpd.conf file and I was able to run some simple commands like ls and who from the browser. However I am unable to run the commands which require the root access for example useradd. Any idea what I need to do to execute the commands which require the root access ? Thanks, Nikhil.

        As Anonymous Monk pointed out, this is a bad idea. In fact, that is precisely why you can't do it: web servers are specifically set up to prevent that sort of thing.

        What do you want to do, anyway?

        When's the last time you used duct tape on a duct? --Larry Wall
Re: System commands using CGI
by blue_cowdawg (Monsignor) on Dec 03, 2012 at 17:06 UTC
        Hi, I am trying to execute system commands from CGI but it doesnt work.If I execute the same code from command line, the code works fine.

    This is a very common "gotcha" that it would seem all Perl programmers and Perl programmer wannabes go through at some point in their Perl travels.

    Stepping back from your original complaint for just a second let me share with you my typical approach for troubleshooting a CGI problem.

    1. First off understand exactly how your web server is set up. What userid is your CGI environment running as being one of the first things I want to know about. Don't assume anything, that's bad for you, stunts your growth, curls your spine and causes you to forget to use strict; in your coding. :-) A handy piece of code that I use is as follows:
      #!/usr/bin/perl -w #----------------------------------- # Script to dump my environment to a browser from CGI. # CAVEAT: Never, ever by all that is holy leave this script in a # production environment use strict; use CGI qw/ :all /; my $cgi = new CGI; print $cgi->headers,$cgi->start_html; # start the show; print hr,b("ENV Dump"); print ul( map { li($ENV{$_} } keys %ENV ); print hr,b("CGI Param Dump"); print ul( map { li($cgi->param($_)) } $cgi->param ); print $cgi->end_html; exit(0);
      This will give you an idea what you are dealing with and will be a big help in troubleshooting.
    2. Find out where your server logs are and start watching them.
    3. Embed some debugging statements into your code.
    4. Run your code and watch all the fun

    Given your original complaint I'd look at system permissions for both running the command in the first place (which is why your code will behave differently at the command line than when run from CGI). Typically CGI is run as a non-elevated user and on some *nix systems it is run as "nobody" or "nofiles" which will eliminate your ability to create/modify files.

    Hope this helps you along your way.

    Peter L. Berghold -- Unix Professional
    Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg
      Helpful, but some syntax errors:


      should be:


      missing closing ")":

      map { li($ENV{$_} } keys %ENV

      should be:

      map { li($ENV{$_}) } keys %ENV

Re: System commands using CGI
by aitap (Curate) on Dec 03, 2012 at 19:00 UTC
    You are trying to run who with a single argument >>/var/www/cgi-bin/new.txt while STDOUT redirection is done by shell and who does'nt use this argument as you might think (see who). Run system("who >>/var/www/cgi-bin/new.txt"); instead (so shell will catch the >>) or use IPC::Run (it can do redirection by itself).
    Sorry if my advice was wrong.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1006794]
Approved by davido
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (4)
As of 2018-05-26 18:54 GMT
Find Nodes?
    Voting Booth?