in reply to Re: Problem with exit status of bash script
in thread Problem with exit status of bash script

interesting code you have there. I need some helping understanding it though

after you fork, does the child process actually modify "my %kids" ? I tried to do something similar with an array, but when I called it I got back a reference to an array. do you know why? (code is below)

in your second loop, you wait for the kids to finish their process and print to stdout the actual return value, is this possible to track? for example I want to have this run all day so I'm thinking I could keep a hash that has these return values and times for tracking purposes

foreach $element (@updevices){ @ip = split(':',$element); die "Could not fork()\n" unless defined ($pid = fork); if ($pid) { push @pids, $pid; next;} system("ping $ip[2] 1 > /dev/null"); $result = $?; print "ping $ip[0] $ip[2] $result\n"; if ( $result != 0) { print "$ip[0] is dead\n"; push(@dead, $ip[0]); } exit; }

Replies are listed 'Best First'.
Re^3: Problem with exit status of bash script
by Anonymous Monk on Dec 05, 2014 at 01:50 UTC
    after you fork, does the child process actually modify "my %kids" ?
    No it doesn't because "The 'exec' function executes a system command and never returns". So
    ... my $pid = fork; $pid == 0 and exec 'ping', '-c', '3', $site; # child ($pid 0) never reaches code below. # exec doesn't return, it can only exit # or it can fail to find ping, but I use autodie # (for this kind of program that's probably # not a great idea in something # that can be called 'production'... but w/e) $kids{$pid} = $site; # only parent gets here ...
    I tried to do something similar with an array, but when I called it I got back a reference to an array. do you know why? (code is below)
    What did you expect? Also I don't see any reference to an array (reference in Perl is something different). Anyway, parent can use the array @pids because why not.
    foreach $element (@updevices){ @ip = split(':',$element); die "Could not fork()\n" unless defined ($pid = fork); if ($pid) { push @pids, $pid; next;} # ^ this is parent code, it pushes $pid to array # and goes back to the top of the loop # below is child code # it does something and then exits system("ping $ip[2] 1 > /dev/null"); $result = $?; print "ping $ip[0] $ip[2] $result\n"; if ( $result != 0) { print "$ip[0] is dead\n"; push(@dead, $ip[0]); } exit; # ^ child exits here # and basically stops (that's how exit works, after all) # and its exit code is 0; see perdoc -f exit } # after parent is done with the loop # it continues here # it has the array @pids # and all other global vars that your script # is full of...
    BTW, note that $? is not exactly exit code. See the manual for details.
    in your second loop, you wait for the kids to finish their process and print to stdout the actual return value, is this possible to track? for example I want to have this run all day so I'm thinking I could keep a hash that has these return values and times for tracking purposes
    There are probably tons of modules on CPAN that help to automatize these kinds of things... I'd really recommend to look there.

    If not, then you probably should use signal handlers ($SIG{CHLD} specifically). See peripc.

      thanks for the help, I did add additional exit codes in the my child processes and it solved my problems (I posted code below)

      in the end, I figured the easiest way is for the parent to keep track of the children's exit status; because in the end that's all I care about.

      I don't have access to "update" my version of perl (or add modules), but I'm definitely going to look more into the IPC, it really interests me.

      foreach $element (@updevices) { @ip = split(':',$element); die "Could not fork()\n" unless defined ($pid = fork); if ($pid) { push @pids, $pid; next;} system("ping $ip[2] 2 > /dev/null"); $result = $?; if ( $result != 0) { print "$ip[0] is dead\n"; exit 1; } exit 0; } for $pid(@pids){ waitpid $pid, 0; if ($? != 0) { $i++; } } print "$i dead devices\n";
        Oh, I see. You were probably asking about the array @dead. I didn't notice it (that's why it's a good idea to use strict and declare all variables). Yeah, parent cannot use @dead because after fork parent and child are two completely different processes and don't share variables (actually, parent can use @dead but it just will be empty).