Deprecated
: htmlspecialchars(): Passing null to parameter #1 ($string) of type string is deprecated in
/www/wwwroot/testblog.58heshihu.com/var/Widget/Archive.php
on line
1057
首页
关于
Search
1
给你10个市场数据调研报告的免费下载网站!以后竞品数据就从这里找!
182 阅读
2
php接口优化 使用curl_multi_init批量请求
144 阅读
3
《从菜鸟到大师之路 ElasticSearch 篇》
107 阅读
4
2024年备考系统架构设计师
104 阅读
5
PHP 文件I/O
92 阅读
php
thinkphp
laravel
工具
开源
mysql
数据结构
总结
思维逻辑
令人感动的创富故事
读书笔记
前端
vue
js
css
书籍
开源之旅
架构
消息队列
docker
教程
代码片段
redis
服务器
nginx
linux
科普
java
c
ElasticSearch
测试
php进阶
php基础
登录
Search
标签搜索
php函数
php语法
性能优化
安全
错误和异常处理
问题
vue
Composer
Session
缓存
框架
Swoole
api
并发
异步
正则表达式
php-fpm
mysql 索引
开发规范
协程
dafenqi
累计撰写
786
篇文章
累计收到
28
条评论
首页
栏目
php
thinkphp
laravel
工具
开源
mysql
数据结构
总结
思维逻辑
令人感动的创富故事
读书笔记
前端
vue
js
css
书籍
开源之旅
架构
消息队列
docker
教程
代码片段
副业
redis
服务器
nginx
linux
科普
java
c
ElasticSearch
测试
php进阶
php基础
页面
关于
搜索到
17
篇与
的结果
2023-08-16
安装tp8遇到报错 Your requirements could not be resolved to an installable set of packages.
Your requirements could not be resolved to an installable set of packages.Your requirements could not be resolved to an installable set of packages. - topthink/think-filesystem[v2.0.0, ..., v2.0.1] require topthink/framework ^6.1 -> found topthink/framework[v6.1.0, ..., v6.1.4] but it conflicts with your root composer.json require (^8.0). - league/mime-type-detection[1.0.0, ..., 1.3.0] require php ^7.2 -> your php version (8.1.4) does not satisfy that requirement. - league/mime-type-detection[1.4.0, ..., 1.12.0] require ext-fileinfo * -> it is missing from your system. Install or enable PHP's fileinfo extension. - topthink/think-filesystem v2.0.2 requires league/flysystem ^2.0 -> satisfiable by league/flysystem[2.0.0, ..., 2.5.0]. - Root composer.json requires topthink/think-filesystem ^2.0 -> satisfiable by topthink/think-filesystem[v2.0.0, v2.0.1, v2.0.2]. ...查看了下资料说是php版本不符,打开composer.json发现代码只要求大于7.0.0可仍然报这个错误,不用太较真执行如下代码之后在运行之前的代码就okcomposer install --ignore-platform-reqs或者composer update --ignore-platform-reqs
2023年08月16日
28 阅读
0 评论
0 点赞
2023-08-11
Nginx+php FastCGI到底是谁影响超时时间
Nginx+php FastCGI到底是谁影响超时时间需求:一个php程序要跑一段时间,但是时间不确定。问题:当该php程序运行超过一段时间被强制断开连接。PHP本身超时处理在 php.ini 中,有一个参数 max_execution_time 可以设置 PHP 脚本的最大执行时间,但是,在 php-cgi(php-fpm) 中,该参数不会起效。真正能够控制 PHP 脚本最大执行时:0s就是说如果是使用 mod_php5.so 的模式运行 max_execution_time 是会生效的,但是如果是php-fpm模式中运行时不生效的。max_execution_time(php.ini中)计算的只是PHP脚本本身执行的时间,执行之外的时间都不会计算在内。哪些属于执行之外的时间呢?包含sleep、数据交互、socket交互等等。配置参数所在位置:php.ini:max_execution_timephp-fpm.conf:request_terminate_timeoutnginx.conf:fastcgi_connect_timeoutfastcgi_read_timeoutfastcgi_send_timeoutrequest_terminate_timeout = 0 即为不受时间控制,永不超时request_terminate_timeout引起的资源问题request_terminate_timeout的值如果设置为0或者过长的时间,可能会引起file_get_contents的资源问题。如果file_get_contents请求的远程资源如果反应过慢,file_get_contents就会一直卡在那里不会超时。我们知道php.ini 里面max_execution_time 可以设置 PHP 脚本的最大执行时间,但是,在 php-cgi(php-fpm) 中,该参数不会起效。真正能够控制 PHP 脚本最大执行时间的是 php-fpm.conf 配置文件中的request_terminate_timeout参数。request_terminate_timeout默认值为 0 秒,也就是说,PHP 脚本会一直执行下去。这样,当所有的 php-cgi 进程都卡在 file_get_contents() 函数时,这台 Nginx+PHP 的 WebServer 已经无法再处理新的 PHP 请求了,Nginx 将给用户返回“502 Bad Gateway”。修改该参数,设置一个 PHP 脚本最大执行时间是必要的,但是,治标不治本。例如改成 30s,如果发生 file_get_contents() 获取网页内容较慢的情况,这就意味着 150 个 php-cgi 进程,每秒钟只能处理 5 个请求,WebServer 同样很难避免”502 Bad Gateway”。解决办法是request_terminate_timeout设置为10s或者一个合理的值,或者给file_get_contents加一个超时参数如果常有请求超时,请打开php-fpm的慢日志,通过日志来确认评估超时时间。Ngnix中的fastcgi 请求时间控制fastcgi_connect_timeout语法:fastcgi_connect_timeout time默认值:fastcgi_connect_timeout 60使用字段:http, server, location指定同FastCGI服务器的连接超时时间,这个值不能超过75秒。fastcgi_read_timeout语法:fastcgi_read_timeout time默认值:fastcgi_read_timeout 60使用字段:http, server, location前端FastCGI服务器的响应超时时间,如果有一些直到它们运行完才有输出的长时间运行的FastCGI进程,或者在错误日志中出现前端服务器响应超时错误,可能需要调整这个值。fastcgi_send_timeout语法:fastcgi_send_timeout time默认值:fastcgi_send_timeout 60使用字段:http, server, location指令为上游服务器设置等待一个FastCGI进程的传送数据时间,如果有一些直到它们运行完才有输出的长时间运行的FastCGI进程,那么可以修改这个值,如果你在上有服务器的error log里面发现一些超时错误,那么可以恰当的增加这个值。指令指定请求服务器的超时时间,指完成了2次握手的连接,而不是完整的连接,如果在这期间客户端没有进行数据传递,那么服务器将关闭这个连接。在Nginx+FastCGI 配置测试中其中在request_terminate_timeout设置为永不超时的情况下,nginx中fastcgi_read_timeout 的设置时间将影响到最终的超时时间。测试中,如果是php-fpm中的超时将显示 502 Bad Gateway502 Bad Gateway502 Bad Gatewaynginx 如果是nginx中cgi配置超时 将显示 504 Gateway Time-out 504 Gateway Time-out 504 Gateway Time-out nginx
2023年08月11日
14 阅读
0 评论
0 点赞
2023-08-11
一文详解PHP的内存泄露
一文详解PHP的内存泄露FPM 的黑魔法首先,传统的跑在 FPM 下的 PHP 代码是没有“内存泄漏”一说的,所谓的内存泄漏就是忘记释放内存,导致进程占用的物理内存(附1)持续增长,得益于 PHP 的短生命周期,PHP 内核有一个关键函数叫做php_request_shutdown此函数会在请求结束后,把请求期间申请的所有内存都释放掉,这从根本上杜绝了内存泄漏,极大的提高了 PHPer 的开发效率,同时也会导致性能的下降,例如单例对象,没必要每次请求都重新申请释放这个单例对象的内存。(这也是Swoole等cli方案的优势之一,因为 cli 请求结束不会清理内存)。Cli 下的内存泄漏相信 PHPer 都遇见过这个报错Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 12288 bytes),是由于向 PHP 申请的内存达到了上限导致的,在 FPM 下一定是因为这次 web 请求有大内存块申请,例如 Sql 查询返回一个超大结果集,但在 Cli 下报这个错大概率是因为你的 PHP 代码出现了内存泄漏。常见的泄漏姿势有:向类的静态属性中追加数据,例如://不停的调用foo() 内存就会一直涨function foo(){ ClassA::$pro[] = "the big string";}向 $GLOBAL 全局变量中追加数据,例如://不停的调用foo() 内存就会一直涨function foo(){ $GLOBAL['arr'][] = "the big string";}向函数的静态变量中追加数据,例如://不停的调用foo() 内存就会一直涨function foo(){ static $arr = []; $arr[] = "the big string";}我们需要检测工具有的同学可能会说很简单嘛,把追加的变量在请求结束后unset()掉就可以了。但真实场景远没有你想的那么简单:例一:function foo(){$obj = new ClassA(); //foo函数结束后将自动释放 $obj对象 $obj->pro[] = str_repeat("big string", 1024);}while (1) {foo(); sleep(1);}上述代码 Cli 运行起来会泄漏吗?肉眼来看肯定不会泄漏,因为foo()函数结束后$obj是栈上的对象自动释放掉了,但答案是可能泄漏也可能没泄漏,这取决于ClassA的定义:class classA{public $pro; public function __construct() { $this->pro = &$GLOBALS['arr']; //pro是其他变量的引用 }}如果ClassA的定义是上面的样子,那么这个例子就是泄漏的!!例二:class Test{public $pro = null; function run() { $var = "Im global var now";//此处 $var 是长生命周期。 $http = new \Swoole\Http\Server("0.0.0.0", 9501, SWOOLE_BASE); $http->on("request", function($req, $resp) { //此处没有给类的静态属性赋值,没有给全局变量赋值, //也没有给函数的静态变量赋值,但是这里是泄漏的,因为 $this 变成长生命周期了。 $this->pro[] = str_repeat("big string", 1024); $resp->end("hello world"); }); $http->start(); echo "run done\n"; //输出不了 //这个函数永远不会结束,局部变量也变成了"全局变量" } }(new Test())->run();new Test()的本意虽然是创建一个临时的对象,但是run()方法触发了server->start()方法,代码将不向下执行,run()函数结束不了,run()函数的局部变量$var和临时对象本身都可以视为全局变量了,给其追加数据都是泄漏的!!例三:由于php_request_shutdown的存在,很多 PHP 扩展其实是有内存泄漏的(emalloc 后没有 efree),但是在 FPM 下是可以正常运行的,而这些扩展放到 Cli 下就会有内存泄漏问题,如果没有工具,Cli 下遇到扩展的泄漏问题,那也只能 gg 了-.-!还有就是当我们调用第三方的类库的函数,要传一个参数,这个参数是全局变量,我不知道这个第三方库会不会给这个参数追加数据,一旦追加数据就会产生泄漏,同理别人给我的函数传的参数我也不敢赋值,第三方函数的返回值有没有全局变量我也不知道。综上我们需要一个检测工具,相对于其他语言 PHP 在这个领域是空白的,可以说没有这个工具整个 Cli 生态就无法真正的发展起来,因为复杂的项目都会遇到泄漏问题。Swoole Tracker可以检测泄漏问题,但它是一款商业产品,现在我们决定重构这个工具,把内存泄漏检测的功能(下文简称Leak工具)完全免费给 PHP 社区使用,完善 PHP 生态,回馈社区,下面我将概述它的具体用法和工作原理。Swoole Tracker 用法Leak工具的实现原理是直接拦截系统底层的 emalloc,erealloc,以及 efree 调用,记录一个巨大的指针表,emalloc/erealloc 的时候添加,efree 的时候删除表中的记录,如果请求结束,指针表中仍然有值就证明产生了内存泄漏,不仅能发现 PHP 代码的泄漏,扩展层甚至 PHP 语言层面的泄漏都能发现,从根本上杜绝泄漏问题。使用方式很简单:前往官网下载最新的 tracker(3.0+) 扩展。php.ini 加入以下配置:extension=swoole_tracker.so;总开关apm.enable=1;Leak检测开关apm.enable_malloc_hook=1在 Cli 模式下主业务逻辑一定是可以抽象成循环体函数的,例如Swoole的OnReceive函数,workerman 的OnMessage函数,以及上文例一中的foo()函数, 在循环体主函数(下文简称主函数)最开始加上trackerHookMalloc()调用即可:function foo(){trackerHookMalloc(); //标记主函数,开始hook malloc $obj = new ClassA(); $obj->pro[] = str_repeat("big string", 1024);}while (1) {foo(); sleep(1);}每次调用主函数结束后(第一次调用不会被记录),都会生成一个泄漏的信息到/tmp/trackerleak日志里面。查看泄漏结果在 Cli 命令行调用trackerAnalyzeLeak()函数即可分析泄漏日志,生成泄漏报告,可以直接php -r "trackerAnalyzeLeak();"即可。下面是泄漏报告的格式:没有内存泄漏的情况:[16916 (Loop 5)] ✅ Nice!! No Leak Were Detected In This Loop其中16916表示进程 id,Loop 5表示第 5 次调用主函数生成的泄漏信息有确定的内存泄漏:[24265 (Loop 8)] /Users/guoxinhua/tests/mem_leak/http_server.php:125 => [12928][24265 (Loop 8)] /Users/guoxinhua/tests/mem_leak/http_server.php:129 => [12928][24265 (Loop 8)] ❌ This Loop TotalLeak: [25216]表示第 8 次调用http_server.php的 125 行和 129 行,分别泄漏了 12928 字节内存,总共泄漏了 25216 字节内存。通过调用trackerCleanLeak()可以清除泄漏日志,重新开始。技术特性(技术难点)支持持续增长检测:想象一个场景,第一次请求运行主函数的时候申请 10 字节内存,然后请求结束前释放掉,然后第二次请求申请了 100 字节,请求结束再释放掉,虽然每次都能正确的释放内存但是每次又都申请更多的内存,最终导致内存爆掉,Leak工具支持这种检测,如果某一行代码有N次(默认 5 次)这种行为就会报"可疑的内存泄漏",格式如下:The Possible Leak As Malloc Size Keep Growth:/Users/guoxinhua/tests/mem_leak/hook_malloc_incri.php:39 => Growth Times : [8]; Growth Size : [2304]表示 39 行有 8 次 malloc size 的增长,总共增长了 2304 字节。支持跨 loop 分析://Swoole Http Server的OnRequest回调$http->on("request", function($request, $response) {trackerHookMalloc(); if(isset(classA::$leak['tmp'])){ unset(classA::$leak['tmp']);//每一次loop都释放上一次loop申请的内存}classA::$leak['tmp'] = str_repeat("big string", 1024);//申请内存 并在本次loop结束后不释放 $response->end("hello world");});按照正常的检测泄漏的理论,上述代码每次都会检测出泄漏,因为每次都给classA::$leak['tmp']赋值并在 Loop 结束也没有释放,但实际业务代码经常这样写,并且此代码也是不会产生泄漏的,因为本次 Loop 的泄漏会在下次释放掉,Leak工具会跨相邻 2 个Loop 进行分析,自动对冲上面这种情况的泄漏信息,如果是跨多个 Loop 的释放,会以如下格式输出:[28316 (Loop 2)] /Users/guoxinhua/tests/mem_leak/hook_efree_pre_loop.php:37 => [-12288]Free Pre (Loop 0) : /Users/guoxinhua/tests/mem_leak/hook_efree_pre_loop.php:42 => [12288][28316 (Loop 2)] /Users/guoxinhua/tests/mem_leak/hook_efree_pre_loop.php:42 => [12288][28316 (Loop 2)] ✅ Nice!! No Leak Were Detected In This Loop上述信息表示 Loop 2 释放了 Loop 0 的 12288 字节内存,然后 Loop 2 又申请了 12288 字节内存,总体来说本次 Loop 跑下来没有内存泄漏。支持循环引用情况:首先简单的介绍一下循环引用问题:function foo(){$o = new classA(); $o->pro[] = $o; //foo结束后 $o无法释放,因为自己引用了自己,即循环引用}while (1) {foo(); sleep(1);}因为循环引用,上面的代码每次运行foo()内存都会增长,但是这个代码确实没有内存泄漏的,因为增长到一定程度 PHP 会开启同步垃圾回收,把这种循环引用的内存都释放掉。但是这给Leak工具带来了麻烦,因为$o的变量是延迟释放的,foo()结束后会报泄漏,而这种写法又确实不是泄漏。Swoole Tracker的Leak工具会自动识别上面的情况,会马上释放循环引用的内存,不会造成误报。如果你发现你的进程内存一直涨,开启了 Tracker 的泄漏检测,通过memory_get_usage(false);打印发现内存不涨了,那么证明你的应用存在循环引用,并且本来就没有内存泄漏问题。支持子协程统计:function loop(){ trackerHookMalloc(); classA::$leak[] = str_repeat("big string", 1024);//申请内存go(function() { echo co::getcid() . "child\n"; go(function() { echo co::getcid()."child2\n"; classA::$leak = [];//释放内存 }); });}Co\run(function(){while (1) { loop(); sleep(1); }});上述代码申请的内存会在第二个子协程里面释放,Leak工具会自动识别协程环境,会在所有子协程都结束后才统计汇总,所以上述代码不会有误报情况。支持 defer,context:$http->on("request", function($request, $response) {trackerHookMalloc(); $context = Co::getContext(); $context['data'] = str_repeat("big string", 1024);//context会在协程结束自动释放 classA::$leak[] = str_repeat("big string1", 1024); defer(function() { classA::$leak = [];//注册defer释放内存 }); $response->end("hello world");});Leak工具会自动识别协程环境,如果存在 defer 和 context,会在 defer 执行结束和 context 释放之后再统计汇总,所以上述代码不会有误报情况,当然如果上面没有注册 defer 也会正确的报告泄漏信息。支持旁路函数干扰排除:例如一个进程由主函数响应请求(OnRequest 等),然后还有个定时器在运行(旁路函数),我们希望检测的是主循环函数的泄漏情况,而当主循环函数执行到一半的时候定时器函数执行了,并申请了内存,然后又切回到主循环函数,此时会误报,Leak工具会支持识别出旁路函数然后不收集旁路函数的 malloc 数据。除了上述这些,Leak工具还支持internd string抓取等等,在此不再展开。注意前几次 Loop 的泄漏信息不用管,因为大部分项目都有一些初始化的缓存是不释放的。检测期间尽量不要有并发。由于开启泄漏检测后性能会非常差,不要在 php.ini 中开启apm.enable_malloc_hook = 1压测。和 Swoole Tracker2.x 的检查泄漏原理不一样,不能一起用。一个进程只能有一个地方调用trackerHookMalloc()函数。Swoole4.5.3由于底层 api 有问题,Leak工具无法正常工作,请升级到最新版Swoole或者降级Swoole版本。附件:免费公开课--如何正确查看进程内存占用
2023年08月11日
13 阅读
0 评论
0 点赞
2023-08-10
PHP session.save_path目录大量session临时文件带来的服务器效率问题
PHP session.save_path目录大量session临时文件带来的服务器效率问题如果访问量大,可能产生的 SESSION 文件会比较多,这时可以设置分级目录进行 SESSION 文件的保存,效率会提高很多,设置方法为:session.save_path="N;/save_path",N 为分级的级数,save_path 为开始目录。当写入 SESSION 数据的时候,PHP 会获取到客户端的 SESSION_ID,然后根据这个 SESSION ID 到指定的 SESSION 文件保存目录中找到相应的 SESSION 文件,不存在则创建之,最后将数据序列化之后写入文件。 检查了下各web节点,所有web服务器的httpd线程均达到满负荷,很奇怪。因为所有web节点都通过nfs来共享session目录来达到 session的一致性,检查了下nfs文件服务器,IO读写比较大,检查了session_tmp目录,发现session目录临时文件达到 70000多个,初步判断也许是因为一级目录下文件过多带来的IO性能下降。以前没有想过session存放的效率问题,今天由此想到了session多级存放的问题,来解决一个目录下session文件过多带来的读写效率问题,查了下php.net其实php在配置中已经给出了有关选项。 php.net上的:http://cn.php.net/manual/zh/ref.session.phpsession.save_path 定义了传递给存储处理器的参数。如果选择了默认的 files 文件处理器,则此值是创建文件的路径。默认为 /tmp。参见 session_save_path()。 此指令还有一个可选的 N 参数来决定会话文件分布的目录深度。例如,设定为 '5;/tmp' 将使创建的会话文件和路径类似于/tmp/4/b/1/e/3/sess_4b1e384ad74619bd212e236e52a5a174If。 要使用 N 参数,必须在使用前先创建好这些目录。在 ext/session 目录下有个小的 shell 脚本名叫 mod_files.sh 可以用来做这件事。此外注意如果使用了 N 参数并且 N 大于 0,那么将不会执行自动垃圾回收,更多信息见 php.ini。另外如果用了 N 参数,要确保将 session.save_path 的值用双引号 "quotes" 括起来,因为分隔符分号( ;)在 php.ini 中也是注释符号。 session.save_path string 在定义session.save_path中可以定义多级存放的路径,修改php.ini session.save_path = "2;/data/session_tmp" 将session文件分成两级存放,即/data/session_tmp/4/b /sess_4b1e384ad74619bd212e236e52a5a174If,取前两位字符,但是php并不生成目录,需要自己手工生成,所以写了个脚本来生成初始的目录。 附上一个创建二级文件夹包的代码。 <?php$string = '0123456789abcdefghijklmnopqrstuvwxyz'; $length = strlen($string);for($i = 0; $i < $length; $i++) {for($j = 0; $j < $length; $j++) { createfolder('/session_tmp/'.$string[$i].'/'.$string[$j]); } }function createfolder($path) {if (!@file_exists($path)) { createfolder(@dirname($path)); @mkdir($path, 0777); }//return $this -> createfolder; }?>session目录分级处理之后,IO处理值增加,http进程降低,web处理效率明显好转
2023年08月10日
7 阅读
0 评论
0 点赞
2023-08-10
如何防止PHP进程异常退出(进程被杀)?
如何防止PHP进程异常退出(进程被杀)?背景通常,在cli下运行的常驻后台PHP进程,可能异常退出,比如php执行过程中出现的致命错误,或被 kill 命令手动杀死等。如下面的php代码:<?phpwhile(1){$content = fgets(STDIN); if(empty($content)){ sleep(1); } //逻辑处理部分代码省略}?>查错我们使用register_shutdown_function可以跟踪到底是什么错误导致的进程退出。(想更多了解register_shutdown_function,请查看博文 妙用php中的register_shutdown_function和fastcgi_finish_request)加入了错误捕捉代码。如下:<?php$is_end = false;function catch_error(){ global $is_end; $time = date('Y-m-d H:i:s'); $error = error_get_last(); $msg = "$time [error]"; if($is_end){ $msg .= "is_end[yes]"; }else{ $msg .= "is_end[no]"; } if($error){ $msg .= var_export($error,1); } echo $msg."\r\n";}register_shutdown_function("catch_error");?>可是,php当进程再次退出时,在日志中并没有记录任何信息。说明register_shutdown_function方法根本没有执行。是什么导致register_shutdown_function方法没有运行呢?在php的官方文档中又这样一个注释:Shutdown functions will not be executed if the process is killed with a SIGTERM or SIGKILL signal. While you cannot intercept a SIGKILL, you can use pcntl_signal() to install a handler for a SIGTERM which uses exit() to end cleanly.注释的意思是当php进程获得SIGTERM和SIGKILL信号而退出时,是不执行register_shutdown_function方法的。可以使用pcntl_signal()方法来捕获信息,并调用相应的处理方法。好,如何检测是信号导致我们的php进程退出的呢?我们加入如下代码:<?phpdeclare(ticks = 1);function sig_handler($signo){ $time = date('Y-m-d H:i:s'); echo $time." exit signo[{$signo}]\r\n"; exit("");}pcntl_signal(SIGTERM, "sig_handler");pcntl_signal(SIGHUP, "sig_handler");pcntl_signal(SIGINT, "sig_handler");pcntl_signal(SIGQUIT, "sig_handler");pcntl_signal(SIGILL, "sig_handler");pcntl_signal(SIGPIPE, "sig_handler");pcntl_signal(SIGALRM, "sig_handler");?>过一段时间,发现php进程退出了,日志中出现了如下日志信息:2014-11-23 18:30:06 exit signo[14]2014-11-23 18:30:06 [error]is_end[no]看来是sigalarm信号导致php进程退出了。这个信号是可以捕获和处理的。kill 命令会发出sigalarm信号。最终的代码如下:<?phpdeclare(ticks = 1);$is_end = false;function catch_error(){ global $is_end; $time = date('Y-m-d H:i:s'); $error = error_get_last(); $msg = "$time [error]"; if($is_end){ $msg .= "is_end[yes]"; }else{ $msg .= "is_end[no]"; } if($error){ $msg .= var_export($error,1); } echo $msg."\r\n";}register_shutdown_function("catch_error");function sig_handler($signo){ $time = date('Y-m-d H:i:s'); if($signo == 14){ //忽略alarm信号 echo $time." ignore alarm signo[{$signo}]\r\n"; }else{ echo $time." exit signo[{$signo}]\r\n"; exit(""); }}pcntl_signal(SIGTERM, "sig_handler");pcntl_signal(SIGHUP, "sig_handler");pcntl_signal(SIGINT, "sig_handler");pcntl_signal(SIGQUIT, "sig_handler");pcntl_signal(SIGILL, "sig_handler");pcntl_signal(SIGPIPE, "sig_handler");pcntl_signal(SIGALRM, "sig_handler");while(1){$content = fgets(STDIN); if(empty($content)){ sleep(1); } //逻辑处理部分代码省略}$is_end = true;?>这时再kill 进程,在日志中就发现了alarm相关的日志,但是php进程依然在。PS:以上代码如果用kill -9命令杀死(SIGKILL信号),还是会退出的。也就是说SIGKILL信号是无法捕获的。参考http://blogread.cn/it/article/7256?f=wb_blogread
2023年08月10日
21 阅读
0 评论
0 点赞
1
2
...
4