php execute a background process - php

I need to execute a directory copy upon a user action, but the directories are quite large, so I would like to be able to perform such an action without the user being aware of the time it takes for the copy to complete.
Any suggestions would be much appreciated.

Assuming this is running on a Linux machine, I've always handled it like this:
exec(sprintf("%s > %s 2>&1 & echo $! >> %s", $cmd, $outputfile, $pidfile));
This launches the command $cmd, redirects the command output to $outputfile, and writes the process id to $pidfile.
That lets you easily monitor what the process is doing and if it's still running.
function isRunning($pid){
try{
$result = shell_exec(sprintf("ps %d", $pid));
if( count(preg_split("/\n/", $result)) > 2){
return true;
}
}catch(Exception $e){}
return false;
}

Write the process as a server-side script in whatever language (php/bash/perl/etc) is handy and then call it from the process control functions in your php script.
The function probably detects if standard io is used as the output stream and if it is then that will set the return value..if not then it ends
proc_close( proc_open( "./command --foo=1 &", array(), $foo ) );
I tested this quickly from the command line using "sleep 25s" as the command and it worked like a charm.
(Answer found here)

You might want to try to append this to your command
>/dev/null 2>/dev/null &
eg.
shell_exec('service named reload >/dev/null 2>/dev/null &');

I'd just like to add a very simple example for testing this functionality on Windows:
Create the following two files and save them to a web directory:
foreground.php:
<?php
ini_set("display_errors",1);
error_reporting(E_ALL);
echo "<pre>loading page</pre>";
function run_background_process()
{
file_put_contents("testprocesses.php","foreground start time = " . time() . "\n");
echo "<pre> foreground start time = " . time() . "</pre>";
// output from the command must be redirected to a file or another output stream
// http://ca.php.net/manual/en/function.exec.php
exec("php background.php > testoutput.php 2>&1 & echo $!", $output);
echo "<pre> foreground end time = " . time() . "</pre>";
file_put_contents("testprocesses.php","foreground end time = " . time() . "\n", FILE_APPEND);
return $output;
}
echo "<pre>calling run_background_process</pre>";
$output = run_background_process();
echo "<pre>output = "; print_r($output); echo "</pre>";
echo "<pre>end of page</pre>";
?>
background.php:
<?
file_put_contents("testprocesses.php","background start time = " . time() . "\n", FILE_APPEND);
sleep(10);
file_put_contents("testprocesses.php","background end time = " . time() . "\n", FILE_APPEND);
?>
Give IUSR permission to write to the directory in which you created the above files
Give IUSR permission to READ and EXECUTE C:\Windows\System32\cmd.exe
Hit foreground.php from a web browser
The following should be rendered to the browser w/the current timestamps and local resource # in the output array:
loading page
calling run_background_process
foreground start time = 1266003600
foreground end time = 1266003600
output = Array
(
[0] => 15010
)
end of page
You should see testoutput.php in the same directory as the above files were saved, and it should be empty
You should see testprocesses.php in the same directory as the above files were saved, and it should contain the following text w/the current timestamps:
foreground start time = 1266003600
foreground end time = 1266003600
background start time = 1266003600
background end time = 1266003610

If you need to just do something in background without the PHP page waiting for it to complete, you could use another (background) PHP script that is "invoked" with wget command. This background PHP script will be executed with privileges, of course, as any other PHP script on your system.
Here is an example on Windows using wget from gnuwin32 packages.
The background code (file test-proc-bg.php) as an exmple ...
sleep(5); // some delay
file_put_contents('test.txt', date('Y-m-d/H:i:s.u')); // writes time in a file
The foreground script, the one invoking ...
$proc_command = "wget.exe http://localhost/test-proc-bg.php -q -O - -b";
$proc = popen($proc_command, "r");
pclose($proc);
You must use the popen/pclose for this to work properly.
The wget options:
-q keeps wget quiet.
-O - outputs to stdout.
-b works on background

Well i found a bit faster and easier version to use
shell_exec('screen -dmS $name_of_screen $command');
and it works.

Here is a function to launch a background process in PHP. Finally created one that actually works on Windows too, after a lot of reading and testing different approaches and parameters.
function LaunchBackgroundProcess($command){
// Run command Asynchroniously (in a separate thread)
if(PHP_OS=='WINNT' || PHP_OS=='WIN32' || PHP_OS=='Windows'){
// Windows
$command = 'start "" '. $command;
} else {
// Linux/UNIX
$command = $command .' /dev/null &';
}
$handle = popen($command, 'r');
if($handle!==false){
pclose($handle);
return true;
} else {
return false;
}
}
Note 1: On windows, do not use /B parameter as suggested elsewhere. It forces process to run the same console window as start command itself, resulting in the process being processed synchronously. To run the process in a separate thread (asynchronously), do not use /B.
Note 2: The empty double quotes after start "" are required if the command is a quoted path. start command interprets the first quoted parameter as window title.

Can you arrange to fork off a separate process, and then run your copy in the background? It's been a while since I did any PHP, but the function pcntl-fork looks promising.

Use this function to run your program in background. It cross-platform and fully customizable.
<?php
function startBackgroundProcess(
$command,
$stdin = null,
$redirectStdout = null,
$redirectStderr = null,
$cwd = null,
$env = null,
$other_options = null
) {
$descriptorspec = array(
1 => is_string($redirectStdout) ? array('file', $redirectStdout, 'w') : array('pipe', 'w'),
2 => is_string($redirectStderr) ? array('file', $redirectStderr, 'w') : array('pipe', 'w'),
);
if (is_string($stdin)) {
$descriptorspec[0] = array('pipe', 'r');
}
$proc = proc_open($command, $descriptorspec, $pipes, $cwd, $env, $other_options);
if (!is_resource($proc)) {
throw new \Exception("Failed to start background process by command: $command");
}
if (is_string($stdin)) {
fwrite($pipes[0], $stdin);
fclose($pipes[0]);
}
if (!is_string($redirectStdout)) {
fclose($pipes[1]);
}
if (!is_string($redirectStderr)) {
fclose($pipes[2]);
}
return $proc;
}
Note that after command started, by default this function closes the stdin and stdout of running process. You can redirect process output into some file via $redirectStdout and $redirectStderr arguments.
Note for windows users:
You cannot redirect stdout/stderr to nul in the following manner:
startBackgroundProcess('ping yandex.com', null, 'nul', 'nul');
However, you can do this:
startBackgroundProcess('ping yandex.com >nul 2>&1');
Notes for *nix users:
1) Use exec shell command if you want get actual PID:
$proc = startBackgroundProcess('exec ping yandex.com -c 15', null, '/dev/null', '/dev/null');
print_r(proc_get_status($proc));
2) Use $stdin argument if you want to pass some data to the input of your program:
startBackgroundProcess('cat > input.txt', "Hello world!\n");

You might try a queuing system like Resque. You then can generate a job, that processes the information and quite fast return with the "processing" image. With this approach you won't know when it is finished though.
This solution is intended for larger scale applications, where you don't want your front machines to do the heavy lifting, so they can process user requests.
Therefore it might or might not work with physical data like files and folders, but for processing more complicated logic or other asynchronous tasks (ie new registrations mails) it is nice to have and very scalable.

A working solution for both Windows and Linux. Find more on My github page.
function run_process($cmd,$outputFile = '/dev/null', $append = false){
$pid=0;
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {//'This is a server using Windows!';
$cmd = 'wmic process call create "'.$cmd.'" | find "ProcessId"';
$handle = popen("start /B ". $cmd, "r");
$read = fread($handle, 200); //Read the output
$pid=substr($read,strpos($read,'=')+1);
$pid=substr($pid,0,strpos($pid,';') );
$pid = (int)$pid;
pclose($handle); //Close
}else{
$pid = (int)shell_exec(sprintf('%s %s %s 2>&1 & echo $!', $cmd, ($append) ? '>>' : '>', $outputFile));
}
return $pid;
}
function is_process_running($pid){
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {//'This is a server using Windows!';
//tasklist /FI "PID eq 6480"
$result = shell_exec('tasklist /FI "PID eq '.$pid.'"' );
if (count(preg_split("/\n/", $result)) > 0 && !preg_match('/No tasks/', $result)) {
return true;
}
}else{
$result = shell_exec(sprintf('ps %d 2>&1', $pid));
if (count(preg_split("/\n/", $result)) > 2 && !preg_match('/ERROR: Process ID out of range/', $result)) {
return true;
}
}
return false;
}
function stop_process($pid){
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {//'This is a server using Windows!';
$result = shell_exec('taskkill /PID '.$pid );
if (count(preg_split("/\n/", $result)) > 0 && !preg_match('/No tasks/', $result)) {
return true;
}
}else{
$result = shell_exec(sprintf('kill %d 2>&1', $pid));
if (!preg_match('/No such process/', $result)) {
return true;
}
}
}

Thanks to this answer: A perfect tool to run a background process would be Symfony Process Component, which is based on proc_* functions, but it's much easier to use. See its documentation for more information.

Instead of initiating a background process, what about creating a trigger file and having a scheduler like cron or autosys periodically execute a script that looks for and acts on the trigger files? The triggers could contain instructions or even raw commands (better yet, just make it a shell script).

If using PHP there is a much easier way to do this using pcntl_fork:
http://www.php.net/manual/en/function.pcntl-fork.php

I am heavily using fast_cgi_finish_request()
In combination with a closure and register_shutdown_function()
$message ='job executed';
$backgroundJob = function() use ($message) {
//do some work here
echo $message;
}
Then register this closure to be executed before shutdown.
register_shutdown_function($backgroundJob);
Finally when the response was sent to the client you can close the connection to the client and continue working with the PHP process:
fast_cgi_finish_request();
The closure will be executed after fast_cgi_finish_request.
The $message will not be visible at any time. And you can register as much closures as you want, but take care about script execution time.
This will only work if PHP is running as a Fast CGI module (was that right?!)

If you are looking to execute a background process via PHP, pipe the command's output to /dev/null and add & to the end of the command.
exec("bg_process > /dev/null &");
Note that you can not utilize the $output parameter of exec() or else PHP will hang (probably until the process completes).

PHP scripting is not like other desktop application developing language. In desktop application languages we can set daemon threads to run a background process but in PHP a process is occuring when user request for a page. However It is possible to set a background job using server's cron job functionality which php script runs.

For those of us using Windows, look at this:
Reference: http://php.net/manual/en/function.exec.php#43917
I too wrestled with getting a program to run in the background in
Windows while the script continues to execute. This method unlike the
other solutions allows you to start any program minimized, maximized,
or with no window at all. llbra#phpbrasil's solution does work but it
sometimes produces an unwanted window on the desktop when you really
want the task to run hidden.
start Notepad.exe minimized in the background:
<?php
$WshShell = new COM("WScript.Shell");
$oExec = $WshShell->Run("notepad.exe", 7, false);
?>
start a shell command invisible in the background:
<?php
$WshShell = new COM("WScript.Shell");
$oExec = $WshShell->Run("cmd /C dir /S %windir%", 0, false);
?>
start MSPaint maximized and wait for you to close it before continuing the script:
<?php
$WshShell = new COM("WScript.Shell");
$oExec = $WshShell->Run("mspaint.exe", 3, true);
?>
For more info on the Run() method go to:
http://msdn.microsoft.com/library/en-us/script56/html/wsMthRun.asp
Edited URL:
Go to https://technet.microsoft.com/en-us/library/ee156605.aspx instead as the link above no longer exists.

New answer to an old question. Using this library, the following code would spawn an asynchronous/parallel PHPThread to do background work.
Must have pcntl, posix, and socket extensions
Designed for/tested in CLI mode.
EZ code sample:
function threadproc($thread, $param) {
echo "\tI'm a PHPThread. In this example, I was given only one parameter: \"". print_r($param, true) ."\" to work with, but I can accept as many as you'd like!\n";
for ($i = 0; $i < 10; $i++) {
usleep(1000000);
echo "\tPHPThread working, very busy...\n";
}
return "I'm a return value!";
}
$thread_id = phpthread_create($thread, array(), "threadproc", null, array("123456"));
echo "I'm the main thread doing very important work!\n";
for ($n = 0; $n < 5; $n++) {
usleep(1000000);
echo "Main thread...working!\n";
}
echo "\nMain thread done working. Waiting on our PHPThread...\n";
phpthread_join($thread_id, $retval);
echo "\n\nOur PHPThread returned: " . print_r($retval, true) . "!\n";

From PHP official documentation(php.net)
<?php
function execInBackground($cmd) {
if (substr(php_uname(), 0, 7) == "Windows"){
pclose(popen("start /B ". $cmd, "r"));
}
else {
exec($cmd . " > /dev/null &");
}
}
?>

I know it is a 100 year old post, but anyway, thought it might be useful to someone. You can put an invisible image somewhere on the page pointing to the url that needs to run in the background, like this:
<img src="run-in-background.php" border="0" alt="" width="1" height="1" />

Related

Running Google Chrome headless with PHP exec doesn’t return output till IIS restarted

My environment is Windows Server 2016 and IIS 10. In my PHP script I’m trying to run Google Chrome in a headless mode to get html code of an external web page:
<?php
$chromeApp = "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe";
$command = "\"$chromeApp\" --headless --disable-gpu \
--dump-dom $urladdress > page.html";
exec ($command);
?>
That code works if I run
>C:\php script.php
from the Command line. It also works if I run the actual command:
>"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" \
--headless --disable-gpu --dump-dom https://google.com > page.html
But if I run that script from a browser it creates empty page.html file and hungs till timeout. However if I restart IIS during its execution I get the page.html file filled with the needed data.
What could be a problem here?
this is not an answer, but too much to put in a comment, exec() doesn't really give much feedback,
first don't do this:
$command = "\"$chromeApp\" ";
because different shells can't agree on how stuff should be quoted, so you should use the escapeshellarg() function instead, also don't do this
--dump-dom $urladdress > page.html
because $urladdress may need to be escaped (and if hackers are able to control your $urladdress, then this is actually an arbitrary code execution vulnerability), do this instead:
$command = escapeshellarg($chromeApp)." --headless --disable-gpu \
--dump-dom ".escapeshellarg($urladdress)." > page.html";
(and if your page.html may have names with special characters too, you should run that name through escapeshellarg() as well.)
but replace exec() with proc_open, tell me what you get from running this:
<?php
declare(strict_types=1);
$urladdress="http://google.com";
$chromeApp = _cygwinify_filepath("C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe");
$command = escapeshellarg($chromeApp)." --headless --disable-gpu --dump-dom ".escapeshellarg($urladdress);
$descriptorspec = array(
0 => array("pipe", "rb"), // by default stdin is inherited, we don't want that so we create a stdin pipe just so we can fclose() it.
1 => array("pipe", "wb"), // stdout
2 => array("pipe", "wb"), // stderr
);
$proc=proc_open($command,$descriptorspec,$pipes);
if(!$proc){
throw new \RuntimeException("failed to create process! \"{$command}\"");
}
$stdout="";
$stderr="";
$fetch=function()use(&$stdout,&$stderr,&$pipes){
$tmp=stream_get_contents($pipes[1]);
if(is_string($tmp) && strlen($tmp) > 0){
$stdout.=$tmp;
}
$tmp=stream_get_contents($pipes[2]);
if(is_string($tmp) && strlen($tmp) > 0){
$stderr.=$tmp;
}
};
fclose($pipes[0]);
$status=array();
while(($status=proc_get_status($proc))['running']){
$fetch();
}
$fetch();
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($proc);
var_dump($stdout,$stderr,$status);
function _uncygwinify_filepath(string $path) : string
{
static $is_cygwin_cache = null;
if ($is_cygwin_cache === null) {
$is_cygwin_cache = (false !== stripos(PHP_OS, "cygwin"));
}
if ($is_cygwin_cache) {
return trim(shell_exec("cygpath -aw " . escapeshellarg($path)));
} else {
return $path;
}
}
function _cygwinify_filepath(string $path) : string
{
static $is_cygwin_cache = null;
if ($is_cygwin_cache === null) {
$is_cygwin_cache = (false !== stripos(PHP_OS, "cygwin"));
}
if ($is_cygwin_cache) {
return trim(shell_exec("cygpath -a " . escapeshellarg($path)));
//return "/cygdrive/" . strtr($path, array(':' => '', '\\' => '/'));
} else {
return $path;
}
}
edit: i wrote use(&$stdout,$stderr,&$pipes) instead of use(&$stdout,&$stderr,&$pipes), sorry, fixed. re-run it if you just ran it without this fix.
You have 4 processes in play here.
W3WP.exe
PHP.exe
CMD.exe
Chrome.exe
CMD.exe is taking the output of Chrome.exe and piping it to your file. It will do that upon completion of Chrome.exe or may do it partially intermittently. When I run similar code to yours above, my Chrome.exe does not finish. I can see Chrome.exe still running in TaskManager consuming 25% CPU (100% on one of my cores).
I'm guessing restarting IIS somehow forces the flush in progress of the commands. In most of my cases, there was data inside the page.html file prior to doing IISReset, thought not all of it. (Windows Explorer showed 0KBs, but opening the file showed data in the file nonetheless).
As for things to try, try at --no-sandbox as an argument as that may be interfering since the process is running under a non-interactive session.

PHP Function Timeout

I'm not an expert with PHP. I have a function which uses EXEC to run WINRS whcih then runs commands on remote servers. The problem is this function is placed into a loop which calls getservicestatus function dozens of times. Sometimes the WINRS command can get stuck or take longer than expected causing the PHP script to time out and throw a 500 error.
Temporarily I've lowered the set timeout value in PHP and created a custom 500 page in IIS and if the referring page is equal to the script name then reload the page (else, throw an error). But this is messy. And obviously it doesn't apply to each time the function is called as it's global. So it only avoids the page stopping at the HTTP 500 error.
What I'd really like to do is set a timeout of 5 seconds on the function itself. I've been searching quite a bit and have been unable to find an answer, even on stackoverflow. Yes, there are similar questions but I have not been able to find any that relate to my function. Perhaps there's a way to do this when executing the command such as an alternative to exec()? I don't know. Ideally I'd like the function to timeout after 5 seconds and return $servicestate as 0.
Code is commented to explain my spaghetti mess. And I'm sorry you have to see it...
function getservicestatus($servername, $servicename, $username, $password)
{
//define start so that if an invalid result is reached the function can be restarted using goto.
start:
//Define command to use to get service status.
$command = 'winrs /r:' . $servername . ' /u:' . $username . ' /p:' . $password . ' sc query ' . $servicename . ' 2>&1';
exec($command, $output);
//Defines the server status as $servicestate which is stored in the fourth part of the command array.
//Then the string "STATE" and any number is stripped from $servicestate. This will leave only the status of the service (e.g. RUNNING or STOPPED).
$servicestate = $output[3];
$strremove = array('/STATE/','/:/','/[0-9]+/','/\s+/');
$servicestate = preg_replace($strremove, '', $servicestate);
//Define an invalid output. Sometimes the array is invalid. Catch this issue and restart the function for valid output.
//Typically this can be caught when the string "SERVICE_NAME" is found in $output[3].
$badservicestate = "SERVICE_NAME" . $servicename;
if($servicestate == $badservicestate) {
goto start;
}
//Service status (e.g. Running, Stopped Disabled) is returned as $servicestate.
return $servicestate;
}
The most straightforward solution, since you are calling an external process, and you actually need its output in your script, is to rewrite exec in terms of proc_open and non-blocking I/O:
function exec_timeout($cmd, $timeout, &$output = '') {
$fdSpec = [
0 => ['file', '/dev/null', 'r'], //nothing to send to child process
1 => ['pipe', 'w'], //child process's stdout
2 => ['file', '/dev/null', 'a'], //don't care about child process stderr
];
$pipes = [];
$proc = proc_open($cmd, $fdSpec, $pipes);
stream_set_blocking($pipes[1], false);
$stop = time() + $timeout;
while(1) {
$in = [$pipes[1]];
$out = [];
$err = [];
stream_select($in, $out, $err, min(1, $stop - time()));
if($in) {
while(!feof($in[0])) {
$output .= stream_get_contents($in[0]);
break;
}
if(feof($in[0])) {
break;
}
} else if($stop <= time()) {
break;
}
}
fclose($pipes[1]); //close process's stdout, since we're done with it
$status = proc_get_status($proc);
if($status['running']) {
proc_terminate($proc); //terminate, since close will block until the process exits itself
return -1;
} else {
proc_close($proc);
return $status['exitcode'];
}
}
$returnValue = exec_timeout('YOUR COMMAND HERE', $timeout, $output);
This code:
uses proc_open to open a child process. We only specify the pipe for the child's stdout, since we have nothing to send to it, and don't care about its stderr output. if you do, you'll have to adjust the following code accordingly.
Loops on stream_select(), which will block for a period up to the $timeout set ($stop - time()).
If there is input, it will var_dump() the contents of the input buffer. This won't block, because we have stream_set_blocking($pipe[1], false) on the pipe. You will likely want to save the content into a variable (appending it rather than overwriting it), rather than printing out.
When we have read the entire file, or we have exceeded our timeout, stop.
Cleanup by closing the process we have opened.
Output is stored in the pass-by-reference string $output. The process's exit code is returned, or -1 in the case of a timeout.

Run shell command asynchronously using PHP and node

I need to execute a shell program that will run a rather long process and I dont want to wait until that process has ended for my PHP script to carry on execution. So far i tried:
1:Pure PHP
exec("longCommand &");
2:Node and php
exec("/usr/local/bin/node nodeLauncher.js &");
Node:
var spawn = require('child_process').spawn,
proc = spawn('longCommand', ['&']);
console.log('return');
In both cases the script carry on execution only after the "longCommand" has returned. Am I doing something wrong?
From PHP's page on exec():
If a program is started with this function, in order for it to
continue running in the background, the output of the program must be
redirected to a file or another output stream. Failing to do so will
cause PHP to hang until the execution of the program ends.
That means, unless you direct the output to a file, exec() is blocking and will pause execution of your PHP script until the command you issued exits.
You can redirect the output to a file, or if you don't care about the output, redirect it to /dev/null.
Finally, yet another alternate could be to fork a new PHP process and exec the command from there. You can fork a new PHP process using pcntl_fork.
for node try passing detached option
var spawn = require('child_process').spawn,
proc = spawn('longCommand', ['&'], { detached: true } );
Node documentation on spawn
Although my filenames used here seems weird, why dont try to look at my working prototype of the raw code below... i can't post the other parts dude as I have attached to it my private DB passwords..eheheh
LINK: http://affiliateproductpromotions.net/sml1r.php
<?php
if(isset($_GET['y']))
$y =false;
else $y =true;
if(isset($_GET['count']))
{
echo getCount($_GET['f'],$y);
exit;
}
if(isset($_GET['stop']) && $_GET['stop']=='true')
{
$fr=fopen("huhu.txt","w");
fwrite($fr,"<script>document.getElementById('send').disabled=false;document.getElementById('stop').disabled=true;document.getElementById('process').innerHTML='<b style=color:GREY>Current Status: Stopped!</b>';document.getElementById('stop').style='width:90px;color:LIGHTYELLOW;background-color:GREY';document.getElementById('send').style='width:90px;color:LIGHTYELLOW;background-color:BLUE';</script>");
fclose($fr);
include('../semail/killexec.php');
sleep(2);
//exit;
}
else
{
header("Connection: close");
ignore_user_abort(); // optional
ob_start();
echo ('Text the user will see');
$size = ob_get_length();
header("Content-Length: $size");
function run_in_background($Command, $Priority = 0)
{
if($Priority)
$PID = shell_exec("nohup nice -n $Priority $Command > /dev/null 2>&1 & echo $!");
else
$PID = shell_exec("nohup $Command > /dev/null 2>&1 & echo $!");
return($PID);
}
function is_process_running($PID)
{
exec("ps $PID", $ProcessState);
return(count($ProcessState) >= 2);
}
//ob_end_clean();
echo("Running hmmsearch. . .");
$ps = run_in_background("hmmsearch $hmmfile $fastafile > $outfile");
$fpf = fopen("pid.txt","w");
fwrite($fpf,exec('ps '.$ps));
fclose($fpf);
while($i<=getCount())
{
$fp2 = fopen("sent1email.txt","w");
fwrite($fp2,getEmailSent($i));
fclose($fp2);
$fp = fopen("haha.txt","w");
fwrite($fp,"$i\n");
// echo("<br> [ ".$i++." ] ");
// ob_flush(); flush();
$i++;
sleep(2);
if($i==getCount())
{
$fr=fopen("huhu.txt","w");
fwrite($fr,"<script>document.getElementById('send').disabled=false;document.getElementById('stop').disabled=true;document.getElementById('process').innerHTML='<b style=color:GREY>Current Status: Finished Sending!</b>';document.getElementById('stop').style='width:90px;color:LIGHTYELLOW;background-color:GREY';document.getElementById('send').style='width:90px;color:LIGHTYELLOW;background-color:BLUE';</script>");
fclose($fr);
sleep(1);
include('../semail/killexec.php');
}
if($i<getCount())
{
$fr=fopen("huhu.txt","w");
fwrite($fr,"<script>document.getElementById('send').disabled=true;document.getElementById('stop').disabled=false;document.getElementById('process').innerHTML='<b style=color:GREY>Current Status: Sending...</b>';document.getElementById('send').style='width:90px;color:LIGHTYELLOW;background-color:GREY';document.getElementById('stop').style='width:90px;color:LIGHTYELLOW;background-color:RED';</script>");
fclose($fr);
sleep(2);
}
}
fclose($fp);
//sleep(1);
ob_end_flush(); // <-- this trash will not work
flush(); // <--- if this garbage dont exist
sleep(5);// <-- but dont worry, a collector is here...
}
?>

how to run php as background process

I have a problem when executing the PHP files as background process.
I have two PHP file as follow :
index.php
<?php
$cmd = "php cmdReadReport.php";
if (substr(php_uname(), 0, 7) == "Windows"){
pclose(popen("start /B ". $cmd, "r"));
}
else {
exec($cmd . " > /dev/null &");
}
?>
cmdReadExcel.php
<?php
$reportname = "./report/lw321.xls";
$thereport = new Report();
$thereport->readReport($reportname)
?>
My goal is to run Report.readReport as background process. readReport function is function which reads Excel file and saves its rows to database.
I have followed the tutorial but there is no result/no rows inserted. Is there anything wrong in the code?
Regards,
You could initiate script execution from client instead of server. Like this:
www.example.com/scripts/cmdReadReport.php?keypass=Giw3m4d9BaJO0ua0WFtG
Then just request this page with CURL or something. This approach is more portable.

How to run a PHP script asynchronously?

I am creating a PHP script that will be run via the command line. As part of this script, there are times where I might need to spawn/fork a different script that could take a long time to complete. I don't want to block the original script from completing. If I were doing this with JavaScript, I could run AJAX requests in the background. That is essentially what I am trying to do here. I don't need to know when the forks complete, just that they start and complete themselves.
How can I run these PHP scripts asynchronously?
foreach ($lotsOfItems as $item) {
if ($item->needsExtraHelp) {
//start some asynchronous process here, and pass it $item
}
}
$pids = array();
foreach ($lotsOfItems as $item) {
if ($item->needsExtraHelp) {
$pid = pcntl_fork();
if ($pid == 0) {
// you're in the child
var_dump($item);
exit(0); // don't forget this one!!
} else if ($pid == -1) {
// failed to fork process
} else {
// you're in the parent
$pids[] = $pid;
}
}
usleep(100); // prevent CPU from peaking
foreach ($pids as $pid) {
pcntl_waitpid($pid, $exitcode, WNOHANG); // prevents zombie processes
}
}
Looking the user contributed notes on exec, it looks like you could use it, check out:
http://de3.php.net/manual/en/function.exec.php#86329
<?php
function execInBackground($cmd) {
if (substr(php_uname(), 0, 7) == "Windows"){
pclose(popen("start /B ". $cmd, "r"));
}
else {
exec($cmd . " > /dev/null &");
}
}
?>
This will execute $cmd in the
background (no cmd window) without PHP
waiting for it to finish, on both
Windows and Unix.
int pcntl_fork ( void )
The pcntl_fork() function creates a child process that differs from the parent process only in its PID and PPID. Please see your system's fork(2) man page for specific details as to how fork works on your system.
details : http://php.net/manual/en/function.pcntl-fork.php
related question : PHP: What does pcntl_fork() really do?
Process control should not be enabled within a web server environment and unexpected results may happen if any Process Control functions are used within a web server environment.
details: http://www.php.net/manual/en/intro.pcntl.php

Categories