Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling

trapping system error

by anu_1 (Acolyte)
on Aug 28, 2010 at 06:08 UTC ( #857812=perlquestion: print w/replies, xml ) Need Help??

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

Hi ... I am trying to get the system error msg when the directory creation is failed. The code is
unless (`mkdir -p "xyz/abc/test"`) { print "Not able to create directory"; die "$!"; }
This code is running in cgi-bin script and is the output displayed as HTML. How to get the system error msg like permission denied... When this code runs ..only the print part is displayed .. Thanks for your help

Replies are listed 'Best First'.
Re: trapping system error
by moritz (Cardinal) on Aug 28, 2010 at 07:09 UTC
    The error message you're talking about is print to the standard error stream, you can get it with
    my $result = qx/ $command 2>&1 /

    But in this case it's probably much easier to use the mkpath function from File::Path (it's a core module).

    Perl 6 - links to (nearly) everything that is Perl 6.
Re: trapping system error
by Khen1950fx (Canon) on Aug 28, 2010 at 11:11 UTC
    I used CGI::Carp and CGI::Debug. You can customize all your error messages and go from there. The BEGIN block redirects the error message to the browser and prints out the message with a little extra from CGI::Debug.
    #!/usr/bin/perl use strict; use warnings; use CGI; use CGI::Debug; use CGI::Carp qw( fatalsToBrowser ); BEGIN { sub carp_error { my $error_message = shift; my $q = new CGI; $q->start_html( "Not able to create directory" ), $q->h1( "Error" ), $q->p( "Not able to create directory" ), $q->p( $q->i( $error_message ) ), $q->end_html; } CGI::Carp::set_message( \&carp_error ); } system("mkdir -p test"); if ($@) { print "Not able to create directory\n"; }
      Thanks for your help..
      The answer is almost always: don't use system. If your question is using mkdir as an example, then the answer is use backticks like:
      my $output = `mkdir -p /what/ever 2>&1`;

      If the command to be run will produce output on stdout as well as errors on stderr, then you'll be better off using one of the modules which will allow you to run a command and receive stderr and stdout separately, like IPC::Run, ...

      If you really meant mkdir specifically, why not use perl's mkdir, or File::Path's mkpath? You won't have to do any error-trapping; you can just ask perl what happened.

Re: trapping system error
by psini (Deacon) on Aug 28, 2010 at 09:18 UTC

    "print" sends its output to STDOUT whilst "die" (like "warn") sends to STDERR. In a CGI environment, STDOUT goes to the browser that requested the page, STDERR to Apache log file; so you can add $! to the print line like

    print "Not able to create directory $!";

    Rule One: "Do not act incautiously when confronting a little bald wrinkly smiling man."

      Hi, Thanks for explaining the problem...I tried what you suggested. But still the system error is not displayed in html I tried to execute the script without cgi.
      unless (`mkdir -p "/xyz/abc/test"`) { die "myerror $!"; }
      Here is the output
      mkdir: cannot access directory /xyz/abc/test. /xyz/abc/test: Permission denied myerror: at ./testerror line 8
      The part after myerror is the line number .
        • print to print to STDOUT and therefore the browser
        • die to print to STDERR and therefore the error log
        By using die you're still saying "I want this in the error log, not sent to the browser".

        You want to say this:

        if (my $output = `mkdir -p /xyz/abc/test 2>&1`) { chomp $output; my $message = "Unable to create directory for (whatever the purpose +was) /xyz/abc/test: $output ($!)"; print $message,"\n"; die $message; exit; }
        This runs your mkdir in a way that captures the output from mkdir's STDERR into $output (if the mkdir works, it doesn't print anything). If there was output from the invoked command, then we chomp the output to remove the trailing newline, and print it to STDOUT - for a CGI program, you must print stuff to STDOUT if you want to see it in the browser.

        Note that we printed a full report on the error, following the old journalistic standard of who, what, when, where, and why:

        1. A descriptive message: why this matters and approximately when it happened during execution
        2. The name of the directory: where we were trying to do the operation
        3. The error message from mkdir and the error code: what the error was
        "who" is the CGI program; if you just have one script, you probably don't need the who; if you have multiple scripts in use by your server, you could print the name of your program (in $0; note that mkdir does this to tell you who failed when it can't create the directory).

        Note that I built the message, printed it with a newline, and then did a die with the message sans newline. This means that the message logged in the error log will have the line number and script name supplied automatically and the one shown in the browser won't. Why? Because the final user of the program does not care about scripts and line numbers, only results. The log gets the script name and line number because only developers read logs, not users, and the developers need to know this stuff, unlike the users.

        Permission denied means the user under which apache executes your programs doesnt have permission to create /xyz/abc/test

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://857812]
Approved by Erez
Front-paged by tye
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (5)
As of 2022-05-17 07:09 GMT
Find Nodes?
    Voting Booth?
    Do you prefer to work remotely?

    Results (65 votes). Check out past polls.