Ich weiß, dass dies ein alter Thread ist, aber es sah so aus, als könnte er eine vollständigere Antwort gebrauchen. So erzeuge ich im Allgemeinen mehrere Prozesse in PHP.
Ein Wort der Warnung: PHP war zum Sterben bestimmt. Das bedeutet, dass die Sprache einige Sekunden lang ausgeführt und dann beendet werden sollte. Obwohl die Speicherbereinigung in PHP einen langen Weg zurückgelegt hat, sollten Sie vorsichtig sein. Überwachen Sie Ihre Prozesse auf unerwarteten Speicherverbrauch oder andere Seltsamkeiten. Beobachten Sie alles eine Zeit lang wie ein Falke, bevor Sie es einstellen und vergessen, und selbst dann sollten Sie die Prozesse ab und zu überprüfen oder sie automatisch benachrichtigen lassen, wenn etwas nicht stimmt.
Als ich das hier abtippte, schien es mir eine gute Idee zu sein, das hier anzubringen github auch.
Wenn Sie bereit sind, das Programm auszuführen, empfehle ich Ihnen, das Protokoll mit tail -f abzufragen, um die Ausgabe zu sehen.
<?php
/*
* date: 27-sep-2015
* auth: robert smith
* info: run a php daemon process
* lic : MIT License (see LICENSE.txt for details)
*/
$pwd = realpath("");
$daemon = array(
"log" => $pwd."/service.log",
"errorLog" => $pwd."/service.error.log",
"pid_file" => $pwd."/",
"pid" => "",
"stdout" => NULL,
"stderr" => NULL,
"callback" => array("myProcessA", "myProcessB")
);
/*
* main (spawn new process)
*/
foreach ($daemon["callback"] as $k => &$v)
{
$pid = pcntl_fork();
if ($pid < 0)
exit("fork failed: unable to fork\n");
if ($pid == 0)
spawnChores($daemon, $v);
}
exit("fork succeeded, spawning process\n");
/*
* end main
*/
/*
* functions
*/
function spawnChores(&$daemon, &$callback)
{
// become own session
$sid = posix_setsid();
if ($sid < 0)
exit("fork failed: unable to become a session leader\n");
// set working directory as root (so files & dirs are not locked because of process)
chdir("/");
// close open parent file descriptors system STDIN, STDOUT, STDERR
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);
// setup custom file descriptors
$daemon["stdout"] = fopen($daemon["log"], "ab");
$daemon["stderr"] = fopen($daemon["errorLog"], "ab");
// publish pid
$daemon["pid"] = sprintf("%d", getmypid());
file_put_contents($daemon["pid_file"].$callback.".pid", $daemon["pid"]."\n");
// publish start message to log
fprintf($daemon["stdout"], "%s daemon %s started with pid %s\n", date("Y-M-d H:i:s"), $callback, $daemon["pid"]);
call_user_func($callback, $daemon);
// publish finish message to log
fprintf($daemon["stdout"], "%s daemon %s terminated with pid %s\n", date("Y-M-d H:i:s"), $callback, $daemon["pid"]);
exit(0);
}
function myProcessA(&$daemon)
{
$run_for_seconds = 30;
for($i=0; $i<$run_for_seconds; $i++)
{
fprintf($daemon["stdout"], "Just being a process, %s, for %d more seconds\n", __FUNCTION__, $run_for_seconds - $i);
sleep(1);
}
}
function myProcessB(&$daemon)
{
$run_for_seconds = 30;
for($i=0; $i<$run_for_seconds; $i++)
{
fprintf($daemon["stdout"], "Just being a process, %s, for %d / %d seconds\n", __FUNCTION__, $i, $run_for_seconds);
sleep(1);
}
}
?>
1 Stimmen
Für solche Dinge ist PHP eigentlich nicht gedacht oder geeignet. Das Forken von Prozessen ist viel teurer als das Erzeugen von Threads, wie es normalerweise gemacht wird.
1 Stimmen
Ich könnte diese Aufgabe problemlos in Python mit Threads erledigen, aber aus bestimmten Gründen ist PHP die einzige Option, die mir zur Verfügung steht.
0 Stimmen
Nun, Python hat seine eigenen Probleme mit Multithreading-Code, vor allem die GIL auf CPython. Jython/IronPython haben dieses Problem nicht, aber ich denke, müssen kompiliert werden.