Webman默认RotatingFileHandler按文件大小而非日期轮转,需手动实现按天切割:动态路径+每分钟检查日期并重建handler,同时注意logrotate兜底配置与协程IO优化。

Webman默认RotatingFileHandler不按天切日志
Webman默认用的RotatingFileHandler只按文件大小轮转,比如设maxFileSize=10 * 1024 * 1024,它会在当前webman.log写满10MB时重命名、新建,完全不看日期。哪怕你传了7作为保留数量,也只是最多留7个文件,不是“保留最近7天”——可能三天就生成两个文件,第五天又写满一个,时间戳错乱,根本没法快速定位某天的日志。
手动实现按天切割需动态路径+定时器重建handler
因为Webman是常驻进程,不能靠重启触发新文件,必须主动干预。核心动作就两步:改日志路径为带日期的动态格式,并每分钟检查日期是否变化,变化时移除旧handler、新建一个指向新日期文件的RotatingFileHandler。
具体操作如下:
- 在
config/log.php中,把filename改成带date()的路径,例如:runtime_path().'/logs/webman_'.date('Y-m-d').'.log' - 在
app/bootstrap.php里注册一个每分钟执行的定时器,用$logger->popHandler()卸载旧handler - 再
new \support\log\MonologExtendHandler(...)构造新handler,注意maxFileSize要设为0(禁用大小轮转) - 别在每次
info()或error()时都new handler,只在日期切换那一刻重建,否则频繁open/close文件句柄会拖慢IO
logrotate可作兜底但无法替代应用层按天切
logrotate适合做系统级兜底,比如防止某天Webman进程卡住没切日志,导致单文件暴涨到GB级。但它不能解决“快速定位某天日志”这个核心需求——因为它轮转后文件名是webman.log.1、webman.log.2.gz这种序号命名,没有日期信息,查5月25号的日志得先解压一堆文件逐个grep。
如果你同时用两种方式,要注意冲突:
Webman 2.2.0版本强化了 TCP/UDP 服务支持,优化路由组管理,并增强异步任务处理能力。结合协程与连接池技术,Webman 能轻松应对高并发场景,适用于网站、接口服务、即时通讯、物联网及游戏开发,兼具高性能、灵活扩展与稳定可靠,是多场景 PHP 服务开发的理想选择。
- 不要让
logrotate也去动webman_2026-05-25.log这类带日期的文件,否则可能切出webman_2026-05-25.log.1,语义混乱 - 建议
logrotate只监控原始未切割的webman.log(即关闭应用层切割时的兜底),或干脆不用,专注做好应用内按天切 -
logrotate配置里加copytruncate,避免Webman还在写文件时被truncate导致丢日志
协程环境下文件IO需避开阻塞式操作
Webman跑在Swoole协程中,如果日志写入过程触发了同步IO(比如某些自定义formatter里调用了file_get_contents),会阻塞整个协程,放大IO压力。这不是日志切割本身的问题,但会加剧“单文件过大导致IO问题”的表象。
检查点包括:
- 确认所有日志handler都基于
MonologExtendHandler,而不是原生StreamHandler - 避免在
LineFormatter的format()方法里做任何磁盘读写或网络请求 - 如果用了自定义
formatter,确保其format()方法是纯内存操作,不依赖外部IO - 大日志量场景下,考虑关掉
debug级别日志,或用BufferHandler缓冲后再批量刷盘
真正难的不是写几行代码切文件,而是理解Webman常驻进程的生命周期和Swoole协程对IO的敏感性。很多人配好了日期路径却忘了定时器重建handler,结果还是每天只写一个文件;也有人加了logrotate却没关应用层切割,两个机制打架,日志文件名变得无法预测。










