- URL: https://www.laruence.com/en/2009/06/11/930.html
- Please include attribution when republishing.
PHP is in many ways a poor fit for a long-running SHELL process. It has no dedicated GC routine, and no effective path to memory management. So if you run PHP as a resident SHELL, you'll frequently be unhappy when memory exhaustion aborts the process.
And if the incoming data is invalid while the script doesn't check it, causing an abort, that will make you unhappy too.
So? What do we do?
Multiple processes....
Why?
Advantages:
1. With multiple processes, once a child process exits, the kernel takes care of reclaiming its resources
2. With multiple processes, a child process exiting abnormally won't take down the whole process thread. The parent process still gets a chance to rebuild the flow.
3. One resident main process that only dispatches tasks makes the logic much clearer.
Then, how do we do it?
Next, we'll use the POSIX and Pcntl function families PHP provides to implement a PHP command interpreter: the main process accepts user input, then forks a child process to execute it, and echoes back the child's exit status.
Here's the code, with comments added. If anything is unclear, look up the relevant functions in the manual, or reply with a comment.
#!/bin/env php
<?php
/** A example denoted muti-process application in php
* @filename fork.php
* @touch date Wed 10 Jun 2009 10:25:51 PM CST
* @author Laruence<laruence@baidu.com>
* @license http://www.zend.com/license/3_0.txt PHP License 3.0
* @version 1.0.0
*/
/** Make sure this function can only run in the SHELL */
if (substr(php_sapi_name(), 0, 3) !== 'cli') {
die("This Programe can only be run in CLI mode");
}
/** Turn off the max execution time limit; in CLI mode this statement is actually unnecessary */
set_time_limit(0);
$pid = posix_getpid(); // get the main process ID
$user = posix_getlogin(); // get the username
echo <<<eod
USAGE: [command | expression]
input php code to execute by fork a new process
input quit to exit
Shell Executor version 1.0.0 by laruence
EOD;
while (true) {
$prompt = "n{$user}$ ";
$input = readline($prompt);
readline_add_history($input);
if ($input == 'quit') {
break;
}
process_execute($input . ';');
}
exit(0);
function process_execute($input) {
$pid = pcntl_fork(); // create a child process
if ($pid == 0) {// child process
$pid = posix_getpid();
echo "* Process {$pid} was created, and Executed:nn";
eval($input); // parse the command
exit;
} else {// main process
$pid = pcntl_wait($status, WUNTRACED); // get the child process exit status
if (pcntl_wifexited($status)) {
echo "nn* Sub process: {$pid} exited with {$status}";
}
}
}
But there's one thing I have to remind you of:
Process Control should not be enabled within a webserver environment and unexpected results may happen if any Process Control functions are used within a webserver environment. -- from the PHP manual
In other words, forget about using multiple processes in PHP web development!
Be First to Comment