Running Job in the Background from Perl Without Waiting for Return

Running job in the background from Perl WITHOUT waiting for return

Essentially you need to 'daemonize' a process -- fork off a child, and then entirely disconnect it from the parent so that the parent can safely terminate without affecting the child.

You can do this easily with the CPAN module Proc::Daemon:

use Proc::Daemon;
# do everything you need to do before forking the child...

# make into daemon; closes all open fds
Proc::Daemon::Init();

Perl: Monitor a background process's output without waiting for it to complete

maybe you could try

open(my $step3, "TEdenovo.py [options] |");

while(<$step3>)
{
last if /step 3 finished successfully/;
}

instead of while(1) ?

How do I make a system call and resume execution without waiting for the call to return?

Short answer, no. This is the entire point of fork(). The only question is whether you call fork() directly, or get something else to do that for you.

As mentioned, you could use the shell's backgrounding operator (&) to do that, but then you're using the shell, and that comes with the usual string-injection attack problem

system("some command with args &");

More directly, you could just do the usual fork() and exec() and then not perform the waitpid() that normally happens, which is where the blocking occurs:

if(fork() == 0) {
exec("some", "command", "with", "args") or die "Cannot exec - $!";
}
# No waitpid here so no waiting

If you're doing that, best also to put a SIGCHLD handler in to ignore when the child does eventually exit, so as not to leave zombies hanging around. At some point near the beginning of the code, put

$SIG{CHLD} = 'IGNORE';

Is there a Perl function like 'system' that doesn't wait for a returned value?

An exec within a fork will work without blocking execution:

if (command is bla) { 
exec "osascript 'something.app'" if fork;
} else {
print $client "invalid command\r\n";
}

How to continue Perl script execution in background?

Orphans, i.e. processes where the parent is no longer there, are usually automatically reaped by the init process. Zombies are a different thing: there the parent process exists but does not care to wait for the child and thus the process is not fully reaped even if it is dead. In your case this would be orphans, so no need to worry about this part.

You might still need to worry about shared file descriptors etc with the parent of the parent in case you've executed your process from a shell. I recommend that you also close all file descriptors but especially stdin, stderr and stdout.

How can I run Perl system commands in the background?

Perl's system function has two modes:

  1. taking a single string and passing it to the command shell to allow special characters to be processed
  2. taking a list of strings, exec'ing the first and passing the remaining strings as arguments

In the first form you have to be careful to escape characters that might have a special meaning to the shell. The second form is generally safer since arguments are passed directly to the program being exec'd without the shell being involved.

In your case you seem to be mixing the two forms. The & character only has the meaning of "start this program in the background" if it is passed to the shell. In your program, the ampersand is being passed as the 5th argument to the xterm command.

As Jakob Kruse said the simple answer is to use the single string form of system. If any of the arguments came from an untrusted source you'd have to use quoting or escaping to make them safe.

If you prefer to use the multi-argument form then you'll need to call fork() and then probably use exec() rather than system().

perl run background job and force job to finish?

This works for me:

$SIG{CHLD}="IGNORE";
my $cmd = "top -b -d 60 -n 300 -u $ENV{USER} >> logfile";
if (my $logger_pid=fork) {
# parent
do_something_for_1to2_hours();
kill 15, $logger_pid;
} else {
# child (logger)
exec($cmd);
}

run process in background without being adopted by init, Perl

You can use threads,

use threads;
my $t = async { system('sleep 3000'); };

# do something in parallel ..

# wait for thread to finish
$t->join;

or fork

sub fasync(&) {
my ($worker) = @_;

my $pid = fork() // die "can't fork!";
if (!$pid) { $worker->(); exit(0); }

return sub {
my ($flags) = @_;
return waitpid($pid, $flags // 0);
}
}

my $t = fasync { system('sleep 3000'); };

# do something in parallel ..

# wait for fork to finish
$t->();


Related Topics



Leave a reply



Submit