引入laravel時(shí),發(fā)現(xiàn)用debug模式啟動(dòng)正常,用demon模式啟動(dòng)則出現(xiàn)異常。
經(jīng)過(guò)排查發(fā)現(xiàn)laravel在命令行啟動(dòng)時(shí),保存了stdout的handle
當(dāng)workerman以demon模式啟動(dòng)時(shí),會(huì)關(guān)閉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);
}
}
增加一個(gè)開(kāi)關(guān),
如果有需要,在任何程序啟動(dòng)前,完成std的重定向。然后在workerman啟動(dòng)時(shí)不再重置
已經(jīng)提交PR,請(qǐng)老大審閱
https://github.com/walkor/workerman/pull/924
如果不關(guān)閉STDOUT,終端關(guān)閉后打印數(shù)據(jù)可能會(huì)導(dǎo)致進(jìn)程退出。
會(huì)關(guān)閉STDOUT,只不過(guò)增加一個(gè)開(kāi)關(guān)判斷,如果已經(jīng)關(guān)閉過(guò)就不再關(guān)閉一次。這樣我可以在程序開(kāi)始的時(shí)候就先手動(dòng)調(diào)用resetStd(), 完成stdout重定向。后續(xù) worker::startAll()的時(shí)候就不會(huì)再次關(guān)閉了。
明白,如果添加功能很謹(jǐn)慎,是否可以考慮將 worker 類的一些方法改為public呢?比如worker::startAll()里面的方法,這樣可以自己控制其中的順序。
或者增加marco功能實(shí)現(xiàn),方便擴(kuò)展功能來(lái)實(shí)現(xiàn)自定義。
直接關(guān)閉STDOUT對(duì)其他框架侵入很大,尤其是Symfony\Component\Console 庫(kù),大量依賴了STDOUT的句柄實(shí)例,任何修復(fù)和兼容方式都是很不友好的硬編碼,除非能控制是否關(guān)閉STDOUT