Suppress Notice of Forked Command Being Killed

Suppress Notice of Forked Command Being Killed

How about disown? This mostly works for me on Bash on Linux.

echo "hello"
sleep 100 &
disown
ps ax | grep sleep | grep -v grep | awk '{ print $1 } ' | xargs kill -9
echo "bye"

Edit: Matched the poster's code better.

Suppress Notice of Forked Command Being Killed

How about disown? This mostly works for me on Bash on Linux.

echo "hello"
sleep 100 &
disown
ps ax | grep sleep | grep -v grep | awk '{ print $1 } ' | xargs kill -9
echo "bye"

Edit: Matched the poster's code better.

How to shield the kill output

The message isn't coming from either kill or the background command, it's coming from bash when it discovers that one of its background jobs has been killed. To avoid the message, use disown to remove it from bash's job control:

sleep 20 &
PID=$!
disown $PID
kill -9 $PID

Background Process stdout Displays After Next Command

The message is printed by bash itself, not by the kill command. So you can't suppress it by redirecting any output in your script.

What you can do is to disable the monitor mode of job control by executing

set +m

Quote from the bash man page:

-m Monitor mode. Job control is enabled. This option is on by default for
interactive shells on systems that support it (see JOB CONTROL above). All
processes run in a separate process group. When a background job
completes, the shell prints a line containing its exit status.

With a +m the monitor mode is disabled.

Perl - How to suppress output from a forked child process

Use the exec LIST form to avoid surprises due to shell quoting. This also requires performing the redirection that the shell would do for you.

use 5.10.0;  # //

my $pid = fork // die "$0: fork: $!"; # / fix Stack Overflow highlighting
if ($pid) {
waitpid $pid, 0 or die "$0: waitpid: $!";
warn "$0: child exited abnormally" if $?;
print ".\n"; # done!
}
else {
open STDOUT, ">", "/dev/null" or die "$0: open: $!";
open STDERR, ">&", \*STDOUT or exit 1;
exec "tar", "zcf", "/tmp/mytarball.gz", "directoryToTarBall";
exit 1;
}

Python forked processes won't die

You have to wait() for the child-process.

Please add the following lines to get things corrected:

import sys
import os
import time

children = []

for i in range(0,3):
pid = os.fork()

if pid == -1:
continue
elif pid == 0:
# Do work...
print 'Child %d spawned' % os.getpid()
sys.exit(0)
else:
children.append(pid)

time.sleep(5)

# ADD NEXT TWO LINES:
for pid in children:
os.waitpid(pid, 0)

for pid in children:
proc_path = '/proc/%d' % pid
if not os.path.exists(proc_path):
print 'Child %d is dead' % pid
else:
print 'Child %d is alive' % pid

The parent must wait() for the child. Please see man 2 waitfor details.

In python you can handle those things with the subprocess module.

How to stop forking in this code

You don't indicate how many processes there may be, but no resource is unlimited and you should limit the number or you'll see a rapid degradation of performance as you reach saturation.

This is even more so when going out on the network since you may be annoying a server (and things will also stop being faster quite soon). Perhaps run up to a few tens of processes at a time?

Then one option is to limit a number of parallel downloads using Parallel::ForkManager. It has a way to return data to parent, so a child can report failure. Then its run_on_finish method can check each batch for such a flag (of failure), and set a variable that controls the forking.

use warnings;
use strict;
use Parallel::ForkManager;

my $pm = Parallel::ForkManager->new(2); # only 2 for a managable demo
my $stop_forking;

# The sub gets 6 parameters, but only first (pid) is always defined
# The last one is what a child process may have passed
$pm->run_on_finish(
sub { $stop_forking = 1 if defined $_[-1] }
);

for my $i (0..9)
{
last if $stop_forking;

$pm->start and next; # forks
my $ret = run_job($i); # child process

# Pass data to parent under a condition
if ($ret eq 'FAIL') { $pm->finish(0, \$ret) } # child exits
else { $pm->finish }
}
$pm->wait_all_children;

sub run_job {
my ($i) = $_[0];
sleep 2;
print "Child: job $i exiting\n";
return ($i == 3 ? 'FAIL' : 1);
}

This stops forking after the batch of jobs within which $i == 3. Add prints for diagnostics.

The "callback" run_on_finish runs only once a whole batch completes. The anonymous sub in it always receives 6 arguments, but only the first one, the child pid, is always defined. The last one has data possibly passed by the child, and when that happens we set the flag. A child can return data by passing a reference to finish method. To only indicate a condition we can simply pass anything. I use \$ret as an example of passing actual data.

See documentation for more, but this does what you ask. For yet far more see Forks::Super.


If you wish to fork as you do, I'd first put in a little sleep there, so you don't bombard the server with too many requests. Your children can talk with the parent using socketpair. The failed child can write while all others can simply close their socket. The parent keeps checking, for example with can_read from IO::Select. There is an example in perlipc. Since you only need children to write to the parent the pipe would suffice as well.

You can also do it with a signal. The child that fails sends (say) SIGUSR1 to the parent, which the parent traps and sets a global variable that controls further forks. This is simpler as the parent only traps that one signal and doesn't care where it comes from. See perlipc and sigtrap pragma.

You can also use a file, much like you do, which is probably simplest since here you don't care about racing issues (whether children writes overlap), but only about an empty file showing up.

However, in all these you'd also want to limit the number of parallel processes.

Finally, there are also modules that help with external commands, for example IPC::Run.


To run the callback right as each child exits use reap_finished_children. See this post.

Killing a forked Windows process in Perl

The Forks::Super module provides many useful facilities for handling forked processes, as well as offering a more portable interface.

This program runs notepad to edit the program's own source file and kills the child process after five seconds. If you need to pass parameters to the command then you should specify it as an anonymous array of values like this. If you use a single string like cmd => qq<notepad "$0"> instead then you will start a copy of cmd.exe which in turn starts notepad.exe, and the kill command will just leave notepad running as an orphan

use strict;
use warnings;

use Forks::Super;

if ( my $pid = fork({ cmd => [ 'notepad', $0 ] }) ) {
sleep 5;
Forks::Super::kill('TERM', $pid);
print "Killed\n";
}

Note that if you want to apply a timeout to the child process then you can write

my $pid = fork({ cmd => 'notepad', timeout => 600 })


Related Topics



Leave a reply



Submit