{"id":19829655,"url":"https://github.com/workbunny/process","last_synced_at":"2025-05-01T14:33:40.263Z","repository":{"id":38202368,"uuid":"504721803","full_name":"workbunny/process","owner":"workbunny","description":"🐇 A lightweight mulit-process helper base on PHP. ","archived":false,"fork":false,"pushed_at":"2023-05-06T02:38:56.000Z","size":46,"stargazers_count":18,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-06T14:51:13.158Z","etag":null,"topics":["multi-process"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/workbunny.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-06-18T02:13:31.000Z","updated_at":"2024-09-25T03:05:59.000Z","dependencies_parsed_at":"2022-08-18T21:40:56.408Z","dependency_job_id":null,"html_url":"https://github.com/workbunny/process","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/workbunny%2Fprocess","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/workbunny%2Fprocess/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/workbunny%2Fprocess/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/workbunny%2Fprocess/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/workbunny","download_url":"https://codeload.github.com/workbunny/process/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251890355,"owners_count":21660503,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["multi-process"],"created_at":"2024-11-12T11:19:29.720Z","updated_at":"2025-05-01T14:33:39.982Z","avatar_url":"https://github.com/workbunny.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n\u003cp align='center'\u003e\u003cimg width='260px' src='https://chaz6chez.cn/images/workbunny-logo.png' alt='workbunny'\u003e\u003c/p\u003e\n\n**\u003cp align='center'\u003eworkbunny/process\u003c/p\u003e**\n\n**\u003cp align='center'\u003e🐇 A lightweight multi-process helper base on PHP. 🐇\u003c/p\u003e**\n\n\u003cdiv align=\"center\"\u003e\n    \u003ca href=\"https://github.com/workbunny/process/actions\"\u003e\n        \u003cimg src=\"https://github.com/workbunny/process/actions/workflows/CI.yml/badge.svg\" alt=\"Build Status\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/workbunny/process/blob/main/composer.json\"\u003e\n        \u003cimg alt=\"PHP Version Require\" src=\"http://poser.pugx.org/workbunny/process/require/php\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/workbunny/process/blob/main/LICENSE\"\u003e\n        \u003cimg alt=\"GitHub license\" src=\"http://poser.pugx.org/workbunny/process/license\"\u003e\n    \u003c/a\u003e\n    \n\u003c/div\u003e\n\n# 简介\n\n这是一个基于ext-pcntl和ext-posix拓展的PHP多进程助手，用于更方便的调用使用。\n\n# 快速开始\n\n```\ncomposer require workbunny/process\n```\n\n- 创建一个子Runtime\n\n```php\n// 使用对象方式\n$p = new \\WorkBunny\\Process\\Runtime();\n$p-\u003echild(function(){\n    var_dump('child');\n});\n```\n\n- 父Runtime执行\n\n```php\n$p = new \\WorkBunny\\Process\\Runtime();\n\n$p-\u003eparent(function(){\n    var_dump('parent'); # 仅输出一次\n});\n\n```\n\n- 快速创建运行多个子Runtime\n\n```php\n$p = new \\WorkBunny\\Process\\Runtime();\n\n$p-\u003erun(function(){\n    var_dump('child');\n},function(){\n    var_dump('parent');\n}, 4); # 1 + 4 进程\n\n```\n\n- 监听子Runtime\n\n```php\n$p = new \\WorkBunny\\Process\\Runtime();\n\n$p-\u003ewait(function(\\WorkBunny\\Process\\Runtime $parent, int $status){\n    # 子进程正常退出则会调用该方法，被调用次数是正常退出的子进程数量\n},function(\\WorkBunny\\Process\\Runtime $parent, $status){\n    # 子进程异常退出则会调用该方法，被调用次数是异常的子进程数量\n});\n```\n\n# 方法\n\n**注：作用范围为父Runtime的方法仅在父Runtime内有有效响应**\n\n|      方法名      |     作用范围      | 是否产生分叉 |                   描述                    |\n|:-------------:|:-------------:|:------:|:---------------------------------------:|\n|    child()    | parentContext |   √    |       分叉一个子Runtime / 替换一个子Runtime       |\n|     run()     | parentContext |   √    |             快速分叉N个子Runtime              |\n|    wait()     | parentContext |   ×    |             监听所有子Runtime状态              |\n|   parent()    | parentContext |   ×    |             为父Runtime增加回调响应             |\n|   isChild()   |    public     |   ×    |              判断是否是子Runtime              |\n|    getId()    |    public     |   ×    |              获取当前Runtime序号              |\n|   getPid()    |    public     |   ×    |             获取当前RuntimePID              |\n|  getPidMap()  | parentContext |   ×    |             获取所有子RuntimePID             |\n|   number()    | parentContext |   ×    |      获取Runtime数量 or 产生子Runtime自增序号      |\n|  setConfig()  |    public     |   ×    |                设置config                 |\n|  getConfig()  |    public     |   ×    |                获取config                 |\n|  getPidMap()  | parentContext |   ×    |             获取所有子RuntimePID             |\n| setPriority() |    public     |   ×    | 为当前Runtime设置优先级 **需要当前执行用户为super user** |\n| getPriority() |    public     |   ×    |             获取当前Runtime优先级              |\n|    exit()     |    public     |   ×    |                  进程退出                   |\n\n# 说明\n\n## 1. 初始化\n\n- Runtime对象初始化支持配置\n  - pre_gc ：接受bool值，控制Runtime在fork行为发生前是否执行PHP GC；**注：Runtime默认不进行gc**\n  - priority：接受索引数组，为所有Runtime设置优先级，索引下标对应Runtime序号；\n如实际产生的Runtime数量大于该索引数组数量，则默认为0；\n\n**注：child()的priority参数会改变该默认值**\n\n**注：priority需要当前用户为super user**\n\n```php\n$p = new \\WorkBunny\\Process\\Runtime([\n    'pre_gc' =\u003e true,\n    'priority' =\u003e [\n        0,  // 主Runtime优先级为0\n        -1, // id=1的子Runtime优先级为-1\n        -2, // id=2的子Runtime优先级为-2\n        -3  // id=3的子Runtime优先级为-3\n    ]\n]);\n```\n\n## 2. fork行为\n\n- 在 **fork** 行为发生后，Runtime对象会产生两个分支\n  - id=0 的父Runtime\n  - id=N 的子Runtime\n\n- **child()** 和 **run()** 之后的代码域会被父子进程同时执行，但相互隔离：\n\n```php\n$p = new \\WorkBunny\\Process\\Runtime();\n$p-\u003echild(function(\\WorkBunny\\Process\\Runtime $runtime){\n    var_dump($runtime-\u003egetId()); # id !== 0\n});\n\nvar_dump('parent'); # 打印两次\n```\n\n```php\n$p = new \\WorkBunny\\Process\\Runtime();\n$p-\u003erun(function (\\WorkBunny\\Process\\Runtime $runtime){\n    \n},function(\\WorkBunny\\Process\\Runtime $runtime){\n\n}, 4);\n\nvar_dump('parent'); # 打印5次\n```\n\n- **child()** 函数可以进行替换子Runtime行为\n\n```php\n$p = new \\WorkBunny\\Process\\Runtime();\n\n// 创建一个子Runtime\n// 假设父RuntimeID === 0，子RuntimeID === 1\n// 假设父RuntimePID === 99，子RuntimePID === 100\n$id = $p-\u003echild(function(\\WorkBunny\\Process\\Runtime $runtime){\n    $runtime-\u003egetId(); // 假设 id === 1\n    $runtime-\u003egetPid(); // 假设 pid === 100\n});\n\nif($p-\u003eisChild()){\n    $id === 0; // $id 在子Runtime的上下文中始终为0\n    posix_getpid() === 100;\n}else{\n    $id === 1;// $id 在当前父Runtime的上下文中为1\n    posix_getpid() === 99;\n}\n\n// 对id === 1的子Runtime进行替换\n// 该用法会杀死原id下的子Runtime并新建Runtime替换它\n// 该方法并不会改变子Runtime的id，仅改变id对应的pid\n$newId = $p-\u003echild(function(\\WorkBunny\\Process\\Runtime $runtime){\n    $runtime-\u003egetId(); # id === 1\n}, 0, $id);\n\nif($p-\u003eisChild()){\n    $id === $newId === 0;\n    posix_getpid() !== 100; // 子Runtime PID发生变化，不再是100\n    // 原PID === 100的子Runtime被kill\n}else{\n    $id === $newId === 1; // $id 没有发生变化\n    posix_getpid() === 99;\n}\n```\n\n- 如需在子Runtime中进行 **fork** 操作，请创建新的Runtime；**不建议过多调用，因为进程的开销远比线程大**\n\n```php\n$p = new \\WorkBunny\\Process\\Runtime();\n$id = $p-\u003echild(function(\\WorkBunny\\Process\\Runtime $runtime){\n    var_dump($runtime-\u003egetId()); # id !== 0\n    var_dump('old-child');\n    \n    $newP = new \\WorkBunny\\Process\\Runtime();\n    $newP-\u003echild(function(\\WorkBunny\\Process\\Runtime $newP){\n        var_dump($newP-\u003egetId()); # id === 0\n        var_dump('new-parent');\n    });\n});\n# run 方法同理\n```\n\n## 3. 指定执行\n\n- 指定某个id的Runtime执行\n\n```php\n$p = new \\WorkBunny\\Process\\Runtime();\n$p-\u003erun(function (){},function(){}, 4);\n\nif($p-\u003egetId() === 3){\n    var_dump('im No. 3'); # 仅id为3的Runtime会生效\n}\n\n# fork同理\n```\n\n- 指定所有子Runtime执行\n\n```php\n$p = new \\WorkBunny\\Process\\Runtime();\n$p-\u003erun(function (){},function(){}, 4);\n\nif($p-\u003eisChild()){\n    var_dump('im child'); # 所有子Runtime都生效\n}\n\n# fork同理\n```\n\n- 指定父Runtime执行\n\n```php\n$p = new \\WorkBunny\\Process\\Runtime();\n$p-\u003erun(function (){},function(){}, 4);\n\nif(!$p-\u003eisChild()){\n    var_dump('im parent'); # 父Runtime都生效\n}\n\n# 或以注册回调函数来执行\n$p-\u003eparent(function(\\WorkBunny\\Process\\Runtime $parent){\n    var_dump('im parent');\n});\n\n# fork同理\n```\n\n## 4. 回调函数相关\n\n- 所有注册的回调函数都可以接收当前的Runtime分支对象：\n\n```php\n$p = new \\WorkBunny\\Process\\Runtime();\n$p-\u003echild(function(\\WorkBunny\\Process\\Runtime $runtime){\n    var_dump($runtime-\u003egetId()); # id !== 0\n});\n$p-\u003eparent(function (\\WorkBunny\\Process\\Runtime $runtime){\n    var_dump($runtime-\u003egetId()); # id === 0\n});\n\n$p-\u003erun(function (\\WorkBunny\\Process\\Runtime $runtime){\n    var_dump($runtime-\u003egetId()); # id !== 0\n},function(\\WorkBunny\\Process\\Runtime $runtime){\n    var_dump($runtime-\u003egetId()); # id === 0\n}, 4);\n```\n\n- **注：注册的父Runtime回调函数内传入的是父Runtime对象，注册的子Runtime回调函数内传入的参数是子Runtime对象**\n\n```php\n$p = new \\WorkBunny\\Process\\Runtime();\n$p-\u003echild(function(\\WorkBunny\\Process\\Runtime $runtime){\n    var_dump('child'); # 生效\n    \n    $runtime-\u003echild(function(){\n        var_dump('child-child'); # 由于fork作用范围为父Runtime，所以不生效\n    });\n});\n\n$p-\u003eparent(function (\\WorkBunny\\Process\\Runtime $runtime){\n    var_dump('parent'); # 生效\n\n    $runtime-\u003echild(function(){\n        var_dump('parent-child'); # 生效\n    });\n});\n\n# run 方法同理\n```\n\n## 5. 其他\n\n- 获取当前Runtime数量\n\n**注：该方法仅父Runtime生效**\n\n```php\n$p = new \\WorkBunny\\Process\\Runtime();\nvar_dump($p-\u003enumber(false)); # 仅父Runtime会输出\n```\n\n- 获取当前RuntimePID\n\n**注：该方法可结合指定执行区别获取**\n\n```php\n$p = new \\WorkBunny\\Process\\Runtime();\nvar_dump($p-\u003egetPid()); # 所有Runtime会输出\n```\n\n- 阻塞监听\n\n**注：该方法仅父Runtime生效**\n\n**注：该方法在会阻塞至所有子Runtime退出**\n\n```php\n$p = new \\WorkBunny\\Process\\Runtime();\n\n// $id RuntimeID\n// $pid 进程PID\n// $status 进程退出状态\n$p-\u003ewait(function($id, $pid, $status){\n    # 子Runtime正常退出时\n}, function($id, $pid, $status){\n    # 子Runtime异常退出时\n});\n```\n\n- 非阻塞监听\n\n**注：该方法仅父Runtime生效**\n\n**注：该方法应配合event-loop的timer或者future进行监听**\n\n```php\n$p = new \\WorkBunny\\Process\\Runtime();\n\n// $id RuntimeID\n// $pid 进程PID\n// $status 进程退出状态\n$p-\u003elisten(function($id, $pid, $status){\n    # 子Runtime正常退出时\n}, function($id, $pid, $status){\n    # 子Runtime异常退出时\n});\n```\n\n- 进程退出\n\n**注：该方法可结合指定执行区别获取**\n\n```php\n$p = new \\WorkBunny\\Process\\Runtime();\n\n$p-\u003eexit(0, 'success');\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fworkbunny%2Fprocess","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fworkbunny%2Fprocess","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fworkbunny%2Fprocess/lists"}