swoole进程基础继续
调用外部程序成为子进程
swoole Process exec
函数文档地址:https://wiki.swoole.com/#/process/process?id=exec
<?php
require 'vendor/autoload.php';
use Swoole\Process;
use Swoole\Coroutine\MySQL;
echo "当前进程ID: ".posix_getpid().PHP_EOL;
cli_set_process_title("my_main"); // 设置了进程名称
$child1 = new Process(function (Process $p) {
// 设置子进程名称
cli_set_process_title("my_child1");
}, false, 0, true);
$child1->start();
Process::signal(SIGCHLD, function ($sig) {
// 必须为 false 非阻塞模式
while ($ret = Process::wait(false)) {
echo "PID={$ret['pid']}\n";
}
});
先写一个简单的代码
echo "wujie".PHP_EOL;
root@8199b542ec1e:/var/www# php child.php
wujie
文档上说:string $execfile
,是指定可执行文件的绝对路径,但是我们这里直接使用php child.php
很明显不是,我们需要先找到php
可执行文件的绝对路径
root@8199b542ec1e:/var/www# which php
/usr/local/bin/php
# 这样执行
$(which php) child.php
或者
/usr/bin/env php child.php
警告
如果php
不在环境变量里,就不能使用env
的方式
<?php
require 'vendor/autoload.php';
use Swoole\Process;
use Swoole\Coroutine\MySQL;
echo "当前进程ID: " . posix_getpid() . PHP_EOL;
cli_set_process_title("my_main"); // 设置了进程名称
$child1 = new Process(function (Process $p) {
// 设置子进程名称
cli_set_process_title("my_child1");
$p->exec("/usr/bin/env", ['php', './child.php']);
echo "abc";
}, true, 0, true);
$child1->start();
while (1) {
$ret = $child1->read();
echo $ret;
usleep(0.5 * 1000 * 1000);
}
Process::signal(SIGCHLD, function ($sig) {
// 必须为 false 非阻塞模式
while ($ret = Process::wait(false)) {
echo "PID={$ret['pid']}\n";
}
});
child.php
<?php
cli_set_process_title("my_child1");
while (1) {
echo "wujie".PHP_EOL;
sleep(5);
}
多进程示例
<?php
use Swoole\Process;
$funcMap = array('methodOne', 'methodTwo', 'methodThree');
$worker_num = 3;//创建的进程数
for ($i = 0; $i < $worker_num; $i++) {
$process = new Process($funcMap[$i]);
$pid = $process->start();
sleep(2);
}
while (1) {
$ret = Process::wait();
if ($ret) {// $ret 是个数组 code是进程退出状态码,
$pid = $ret['pid'];
echo PHP_EOL . "Worker Exit, PID=" . $pid . PHP_EOL;
} else {
break;
}
}
function methodOne(Process $worker)
{// 第一个处理
echo $worker->pid . PHP_EOL;
}
function methodTwo(Process $worker)
{// 第二个处理
echo $worker->pid . PHP_EOL;
}
function methodThree(Process $worker)
{// 第三个处理
echo $worker->pid . PHP_EOL;
}
简易进程管理器
读取配置、启动多个子进程
使用parse_ini_file
解析配置文件获取配置参数
p.conf
[childs]
child1=/usr/bin/env php /data/work/php/process/swoolepro/child1.php
child2=/usr/bin/env php /data/work/php/process/swoolepro/child2.php
<?php
$config = parse_ini_file("./pm/p.conf", true);
var_dump($config);
➜ swoolepro php test.php
array(1) {
["childs"]=>
array(2) {
["child1"]=>
string(60) "/usr/bin/env php /data/work/php/process/swoolepro/child1.php"
["child2"]=>
string(60) "/usr/bin/env php /data/work/php/process/swoolepro/child2.php"
}
}
函数集中编写
functions.php
<?php
function init()
{
$config = parse_ini_file("./pm/p.conf", true);
$childs = $config['childs'];
foreach ($childs as $key => $value) {
// key 作为进程名称
// value 根据空格切为数组
$exec_params = explode(' ', $value);
$p = new Swoole\Process(function (\Swoole\Process $process) use ($exec_params) {
// 0: 可执行文件路径
// 后面 需要执行的内容
$process->exec($exec_params[0], array_slice($exec_params, 1));
});
$p->start();
}
}
准备2个子进程执行的程序
<?php
cli_set_process_title("mychild 1");
while (1) {
echo "child1".PHP_EOL;
sleep(5);
}
<?php
cli_set_process_title("mychild 2");
while (1) {
echo "child2".PHP_EOL;
sleep(5);
}
主进程代码
pm.php
<?php
//require "../vendor/autoload.php";
require_once "./pm/functions.php";
use Swoole\Process;
echo "当前进程ID: " . posix_getpid() . PHP_EOL;
cli_set_process_title("my_main");
init();
while (1) {
$ret = Process::wait();
if ($ret) {
$pid = $ret['pid'];
echo PHP_EOL . "Worker Exit, PID=" . $pid . PHP_EOL;
} else {
break;
}
}
配合一段C代码
demo1.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
pid_t pid = 0;
void sigchld_handler(int sig) {
printf("father call the SIGCHLD signal handler. num=%d\n", sig);
}
int main()
{
signal(SIGCHLD,sigchld_handler);
pid = fork();
if(pid == -1){
exit(1);
} else if(pid == 0){ // child code
printf("child process is running, pid = %d.\n",getpid());
} else { // father code
pause();
printf("father process runs again.\n");
}
return 0;
}
gcc demo1.c
./demo1.out
child process is running, pid = xxxx
father call the SIGCHLD signal handler. num=11
father process runs again.