PHP调用bash脚本时Boost::log标准输出仅在程序执行结束后显示怎么办
根因说明
程序的标准输出缓冲策略由输出目标决定:
- 输出到终端(TTY)时,默认使用行缓冲,每输出一行就自动刷新缓冲区
- 输出到管道、文件等非TTY目标时,默认使用全缓冲,缓冲区满(默认4KB)或程序退出时才会统一刷新
你用到的boost::log默认遵循系统缓冲规则,通过PHP调用时输出目标是管道,因此不会主动实时刷新输出,所有日志会攒到mybinary执行结束才统一吐出,这就是你只能先拿到-- starting --、后续日志延迟出现的原因。
你之前尝试在shell层做输出重定向、加tee、PHP侧调用fflush都无效,因为缓冲是mybinary进程内部的用户空间缓冲区,外层操作无法主动触发内部缓冲区刷新。
解决方案
按优先级从高到低可选以下三种方案:
1. 修改boost::log配置(最优)
直接修改mybinary的代码,强制boost::log的控制台输出开启自动刷新,从根源解决问题,不需要依赖外部工具:
// 初始化boost.log时添加以下配置 auto console_sink = boost::log::add_console_log(std::cout); console_sink->locked_backend()->auto_flush(true);
设置后无论运行在什么环境,每次写日志都会主动刷新缓冲区,实现实时输出。
2. 用stdbuf调整缓冲模式(无需改代码)
如果不能修改mybinary的代码,可使用系统自带的stdbuf工具(属于coreutils,绝大多数Linux发行版默认预装),在启动时强制指定标准输出为行缓冲模式:
修改myscript.sh中的执行语句:
$PRE stdbuf -oL $EXE $ARGS
参数-oL表示标准输出采用行缓冲模式,每输出一行就自动刷新。
3. 用unbuffer模拟终端环境
如果stdbuf不生效(部分静态编译的程序不识别stdbuf的修改),可以安装expect包,用自带的unbuffer工具为程序模拟TTY运行环境,触发程序默认的行缓冲策略:
先安装expect:sudo apt install expect(Debian/Ubuntu系)或sudo yum install expect(RHEL/CentOS系)
再修改myscript.sh中的执行语句:
$PRE unbuffer $EXE $ARGS
修改完成后可以先在终端执行./myscript.sh | cat验证输出是否实时,验证通过后再通过PHP调用即可实现流式写入日志文件。
内容的提问来源于stack exchange,提问作者Dominic
相关产品推荐
相关产品推荐

