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:
- taking a single string and passing it to the command shell to allow special characters to be processed
- 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
Tcpdf and Insert an Image Base64 Encoded
How to Make a Select in PHP/MySQL Case Insensitive
How to Launch a PHP Script at Apache Startup
Destination Path for Move_Uploaded_File in PHP
Get Request from PHP Using File_Get_Contents with Parameters
PHP Domdocument - Get HTML Source of Body
Using PHP, How to Insert Text Without Overwriting to the Beginning of a Text File
PHP Get Height and Width in PDF File Proprieties
Replace the Last Comma with an & Sign
Symfony & Guard: "The Security Token Was Removed Due to an Accountstatusexception"
Laravel Session Expire Time for Each Session
PHP Making a Download Counter Without Leaving the Current Page