I'd like to run a curl command and only have content written to stdout if there is an error.

When I run the command from the terminal I get this functionality by default. When I run the command from within a perl script though (``), it outputs the progress info but not any error messages.

I'm able to hide the progress info by appending the -s (--silent) flag, but I can't force errors to be displayed the way they do when ran directly from bash. The -S (--show-errors) flag seems to have no effect.

I've also tried playing with diverting the output to /etc/null, but this seems to prevent anything from being output at all.

my $curl_result = `curl -s -S -X PUT "$url" -H "$h1" -H "$h2" -H "$h3"  -d  "$data"`;

Below is an example of the kind of error I'd like to look for. This one is caused by a purposefully malformed IP:

    "message":"One or more of the given records is invalid",
    "fields": [{
        "message":"Invalid [ipaddress] provided for record data, [test].",
    "errors":["Invalid [ipaddress] provided for record data, [test]."]

You need to distinguish between errors that curl sees, and errors that your http server is returning. The latter are not errors for curl. You can however easily inspect the http status code by adding to your curl the option

 -w '\n%{http_code}\n'

This will append to stdout the HTTP header, which is 200 for OK. So your perl can do something like

my $curl_result = `curl -s -S -w '\n%{http_code}\n' ... 2>/dev/null`;
my @lines = split(/\n/,$curl_result);
my $httpcode = $lines[-1];
if($httpcode eq 200){ print "ok\n"; }
else{ print "error\n"; }
  • That got me to my answer, thanks! I should note that the response lines weren't terminated by \n chars so the split line didn't do anything. $curl_result came back with the value null200. I was content though with if(index($curl_result, "200") != -1). – Nathan Wiles Apr 16 '18 at 14:17
  • I suppose you could use -w '\n%{http_code}\n' (with an extra newline at the start) to ensure there is a split. – meuh Apr 16 '18 at 14:34
  • That did the trick. I also used the 2>/dev/null clause recommended elsewhere to get rid of any other info that we wouldn't want. – Nathan Wiles Apr 16 '18 at 14:49
  • Oops. Sorry, I rejected your edit by mistake. I'll put it back in. – meuh Apr 16 '18 at 14:53

Perl's backtick operator will return (to your $curl_result variable) the STDOUT of the command you run. STDERR from that command will carry through to the calling program/terminal of your perl script -- perhaps to your screen, as if you had called curl yourself.

In order to capture the STDERR, you must (as you began to imagine) drop STDOUT or commingle the two.

Here's an example of dropping STDOUT and redirecting STDERR to STDOUT so that it (instead of the "normal" STDOUT) is captured by the perl variable:

my $curl_result = `curl ... 2>&1 1>/dev/null`;

Alternatively, commingle the two:

my $curl_result = `curl ... 2>&1`;

I omitted the middle of the bulk curl command to make it clear what part I changed. The first example changes STDERR to point instead to where STDOUT is currently pointing, then tells STDOUT to go away. The second example tells STDERR to point to STDOUT, commingling the two.

  • Thanks for the reply. This is what I'd done when I'd mentioned diverting the output to /etc/null. When I add the appendation 2>&1 1>/dev/null and modify the code to fail on purpose, it still does so quietly with no complaint. – Nathan Wiles Apr 16 '18 at 1:15
  • Any stderr should be captured in the variable; are you checking the $? variable for return status? – Jeff Schaller Apr 16 '18 at 1:29
  • That's my understanding, too. I feel like I'm missing something fundamental here. The value of $? seems to be 0 regardless of whether or not the server accepts the curl request. – Nathan Wiles Apr 16 '18 at 2:58
  • You may have to grep the output for indicators of success or failure, then. – Jeff Schaller Apr 16 '18 at 3:12
  • Is there a way to do that when I don't have access to the output from within the perl script? That's have I've been trying to get access to. – Nathan Wiles Apr 16 '18 at 3:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.