引入laravel时,发现用debug模式启动正常,用demon模式启动则出现异常。
经过排查发现laravel在命令行启动时,保存了stdout的handle
当workerman以demon模式启动时,会关闭stdout的handle,并重定向到文件中。
/**
* Redirect standard input and output.
*
* @param bool $throwException
* @return void
* @throws Exception
*/
public static function resetStd(bool $throwException = true): void
{
if (!static::$daemonize || DIRECTORY_SEPARATOR !== '/' || static::$hasResetStd) {
return;
}
global $STDOUT, $STDERR;
$handle = fopen(static::$stdoutFile, "a");
if ($handle) {
unset($handle);
set_error_handler(function () {
});
if ($STDOUT) {
fclose($STDOUT);
}
if ($STDERR) {
fclose($STDERR);
}
if (is_resource(STDOUT)) {
fclose(STDOUT);
}
if (is_resource(STDERR)) {
fclose(STDERR);
}
$STDOUT = fopen(static::$stdoutFile, "a");
$STDERR = fopen(static::$stdoutFile, "a");
// Fix standard output cannot redirect of PHP 8.1.8's bug
if (function_exists('posix_isatty') && posix_isatty(2)) {
ob_start(function ($string) {
file_put_contents(static::$stdoutFile, $string, FILE_APPEND);
}, 1);
}
// change output stream
static::$outputStream = null;
static::outputStream($STDOUT);
restore_error_handler();
//mark as reset
static::$hasResetStd = true;
return;
}
if ($throwException) {
throw new RuntimeException('Can not open stdoutFile ' . static::$stdoutFile);
}
}
增加一个开关,
如果有需要,在任何程序启动前,完成std的重定向。然后在workerman启动时不再重置
已经提交PR,请老大审阅
https://github.com/walkor/workerman/pull/924
如果不关闭STDOUT,终端关闭后打印数据可能会导致进程退出。
会关闭STDOUT,只不过增加一个开关判断,如果已经关闭过就不再关闭一次。这样我可以在程序开始的时候就先手动调用resetStd(), 完成stdout重定向。后续 worker::startAll()的时候就不会再次关闭了。
直接用 Worker::$daemonize 控制吧。
workerman作为底层不会随意添加属性或者方法,除非是十分必要。
明白,如果添加功能很谨慎,是否可以考虑将 worker 类的一些方法改为public呢?比如worker::startAll()里面的方法,这样可以自己控制其中的顺序。
或者增加marco功能实现,方便扩展功能来实现自定义。
直接关闭STDOUT对其他框架侵入很大,尤其是Symfony\Component\Console 库,大量依赖了STDOUT的句柄实例,任何修复和兼容方式都是很不友好的硬编码,除非能控制是否关闭STDOUT