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

IPC::System::Simple: Why isn't my exception caught?

by karlgoethebier (Abbot)
on Nov 20, 2013 at 12:44 UTC ( [id://1063512]=perlquestion: print w/replies, xml ) Need Help??

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

Hi all,

I got stuck with this snippet:

#!/usr/bin/perl use IPC::System::Simple qw( capture ); use strict; use warnings; my $result; my $file = $0; eval{ $result = capture("cat $file | wc -l"); }; if ($@) {print "Error: $@"} print qq(capture $file: $result); $file = qq(foo); undef $result; eval{ $result = capture("cat $file | wc -l"); }; if ($@) {print "Error: $@"} print qq(capture $file: $result); __END__ ./test.pl capture ./test.pl: 32 cat: foo: Datei oder Verzeichnis nicht gefunden capture foo: 0

File foo doesn't exist, but the error i get ist from cat:

cat: foo: Datei oder Verzeichnis nicht gefunden

What do is miss?

Update:

I've been playing around a bit with IPC::Run, here is what i did:

OK, it's still the same idiotic shell command, but for practicing purposes it's good.

#!/usr/bin/perl use strict; use warnings; use IPC::Run qw( run harness ); use Try::Tiny; use Carp; my $file = shift || $0; my @cat = ( "cat", $file ); my @wc = qw( wc -l ); my ( $error, $result ); my @command = ( \@cat, '|', \@wc, '1>', \$result, '2>', \$error ); my $harness = harness @command; try { run $harness; croak $error if $harness->full_result; } catch { print qq(Error: $_); }; chomp $result; printf( "%s:\t%s\n", "result", $result ); printf( "%s:\t%s\n", "cat", $harness->full_result(0) ); printf( "%s:\t%s\n", "wc", $harness->full_result(1) ); __END__

Best regards and thanks for any help, Karl

P.S.: Yes, i know the command is idiotic, i could say wc -l file...it's just for testing.

«The Crux of the Biscuit is the Apostrophe»

Replies are listed 'Best First'.
Re: IPC::System::Simple: Why isn't my exception caught?
by kschwab (Vicar) on Nov 20, 2013 at 14:01 UTC
    It's the pipe. The exit value of something you pass to a shell, if it's a piped sequence, is the exit value of the last command:
    $ cat nosuchfile | wc -l cat: nosuchfile: No such file or directory $ echo $? 0 $ cat nosuchfile cat: nosuchfile: No such file or directory $ echo $? 1
    Some unix shells have workarounds for this, like the PIPESTATUS environment variable, or "set -o pipefail" in bash. Also, IPC::Run provides a built-in mechanism to pipe shell commands together and get the return value of all of them. Personally, I just avoid spawning shell commands with pipes, since it's usually the output of the first command that's interesting, and the function of the second command is almost always easily done within perl (sort, grep, tail, wc, etc).
Re: IPC::System::Simple: Why isn't my exception caught?
by stefbv (Curate) on Nov 20, 2013 at 13:56 UTC

    There is no error because the exit value for "cat $file | wc -l" is 0 (zero).

    Change the command to "wc -l file", as you say, and you get the error.

    use IPC::System::Simple qw( capture $EXITVAL); use strict; use warnings; use Try::Tiny; my $file = 'foo'; my $result; try { $result = capture("cat $file | wc -l"); } catch { print "Error: $_"; }; print "Exitval is $EXITVAL";

      D'oh! I should have known this.

      But surprisingly:

      user@SVN:/svn/dumps> cat foo cat: foo: Datei oder Verzeichnis nicht gefunden user@SVN-Prod1:/svn/dumps> echo $? 1 user@SVN:/svn/dumps> cat foo | wc -l cat: foo: Datei oder Verzeichnis nicht gefunden 0

      I admit, that i didn't ask efficiently.

      What i actually want to do is:

      qx(/usr/local/csvn/bin/svnadmin -q dump $repos | /usr/bin/gzip > $dump);

      Respectively:

      capture("/usr/local/csvn/bin/svnadmin -q dump $repos | /usr/bin/gzip > $dump");

      And i wanted to know (and trap the exceptions) if any part of my piped command fails.

      Some time ago i saw an example on PM that managed this using system and IPC::IPC::Open3. I didn't find the example yet.

      Thank you very much and best regards, Karl

      «The Crux of the Biscuit is the Apostrophe»

Re: IPC::System::Simple: Why isn't my exception caught?
by ikegami (Patriarch) on Nov 20, 2013 at 17:36 UTC
    capture('bash', '-o', 'pipefail', '-c', 'cat "$1" | wc -l', 'dummy', $file)

    This also solves your problem with file names with spaces or other shell metachars.

    This is just an example, right? Cause you could use the following or a small amount of Perl code.

    capture('wc', '-l', $file)

      Your advice looks a bit like hermetism to me - for the moment ;-)

      So i need just a moment to think about/try it.

      But BTW, here is what i figured out in a hurry using IPC::Run as advised by kschwab:

      #!/usr/bin/env perl + use IPC::Run qw( start finish ); use strict; use warnings; my @cat = qw( cat foo ); my @wc = qw( wc -l); my $h = start \@cat, '|', \@wc, '2>', '/dev/null'; $h->finish; print $h->full_result(0) . qq(\n); print $h->full_result(1) . qq(\n); __END__ karls-mac-mini:Desktop karl$ ./ipc.pl + 0 + 1 + 0

      Looks good/like expected. Best regards, Karl

      «The Crux of the Biscuit is the Apostrophe»

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1063512]
Approved by marto
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (5)
As of 2024-04-16 11:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found