how to terminate a command that has started in a perl script, using 'system()'

Viewed 212

I have written a Perl script to run some given commands through the script.

system("my_command");

After running my Perl script, the "my_command" is starting on the Linux terminal properly. Later, I killed my script using 'ctrl+z; kill %%'. but the "my_command" is still running. I tried 'kill %%' again several times but the "my_command" did not terminate. ("my_command" is another Perl script that working properly).

What I need is, if I terminate the initial Perl script/runner then all commands that have been started using 'system()' should be terminated.

Is there any way to achieve this.?

1 Answers

system isn't so useful for this. Consider using open2 which returns the process identifier for the started child process.

use IPC::Open2;

# A system() like call using open2():

my $pid = open2('>&STDOUT', '<&STDIN', @CommandLine);

You can now kill and waitpid on $pid.

Here's an example using some old school OOP so that all the processes you've started will be killed automatically when your program exits. I'm sure there are ready perl packages encapsulating this in a more complete fashion, but this should give you the general idea.

#!/usr/bin/perl

use strict;
use warnings;

package mysystem;

use IPC::Open2;

sub new {
    my $class=shift;

    bless {
        'pid' => open2('>&STDOUT', '<&STDIN', @_)
    }, $class;
}

sub DESTROY {
    my $self = shift;
    $self->kill(15);  # or whatever signal you want to send to it
    $self->wait;
    print "DEBUG PRINTOUT: DONE\n";
}

sub wait {
    # wait for the process to terminate
    my $self = shift;
    waitpid($self->{pid}, 0);
}

sub kill {
    # send a signal to the process
    my ($self, $signal) = @_;
    kill($signal, $self->{pid});
}

sub alive {
    # check if the process is alive
    my $self = shift;
    $self->kill(0) == 1;
}

sub run {
    # do like system(), start a sub process and wait for it
    my $sys = new(@_);
    $sys->wait;
}

package main;

sub handler {
    print "Caught signal @_ - exiting\n";
    exit(0);
}

$SIG{INT} = \&handler;

my $proc = mysystem->new('sleep', '1000');
print "Pid ". $proc->{pid} . " is " . ($proc->alive()?"alive":"dead") . "\n";

print "Letting the destructor kill it\n";

Possible output:

Pid 3833402 is alive
Letting the destructor kill it
DEBUG PRINTOUT: DONE
Related