天天看点

php tp6 错误日志接管分析,ThinkPHP6 记录日志 Permission denied 的解决方法

最近用ThinkPHP6.0写了一个项目,提交到线上测试时发现后台登录后又被中间件重定向到了登录页面,导致后台无法正常使用,绑定了异常处理接管,打开数据库查看异常日志,发现两处异常:

'file' => 'vendor/topthink/think-log/src/log/driver/File.php',

'line' => 123,

'message' => 'error_log(/201907/09.log): failed to open stream: Permission denied'

'file' => 'vendor/topthink/framework/src/think/Cookie.php',

'line' => 203,

'message' => 'Uncaught think\\exception\\ErrorException: Cannot modify header information - headers already sent by (output started at .......'

查看源码

// vendor/topthink/think-log/src/log/driver/File.php

protected function write(array $message, string $destination): bool

{

// 检测日志文件大小,超过配置大小则备份日志文件重新生成

$this->checkLogSize($destination);

$info = [];

foreach ($message as $type => $msg) {

$info[$type] = is_array($msg) ? implode(PHP_EOL, $msg) : $msg;

}

$message = implode(PHP_EOL, $info) . PHP_EOL;

return error_log($message, 3, $destination); // 123

}

// vendor/topthink/framework/src/think/Cookie.php

protected function saveCookie(string $name, string $value, int $expire, string $path, string $domain, bool $secure, bool $httponly): void

{

setcookie($name, $value, $expire, $path, $domain, $secure, $httponly); // 203

}

应该是error_log没有权限,抛出了异常,导致setcookie失败,果断chomd -R 777 runtime/,刷新重试,依然出现一样的错误。runtime已经777了还报Permission denied,难道日志目录不在runtime,查看日志配置文件

// +----------------------------------------------------------------------

// | 日志设置

// +----------------------------------------------------------------------

return [

// 默认日志记录通道

'default' => 'file',

// 日志记录级别

'level' => [],

// 日志类型记录的通道 ['error'=>'email',...]

'type_channel' => [],

// 是否关闭日志写入

'close' => false,

// 日志通道列表

'channels' => [

'file' => [

// 日志记录方式

'type' => 'File',

// 日志保存目录

'path' => '',

// 单文件日志写入

'single' => false,

// 独立日志级别

'apart_level' => [],

// 最大日志文件数量

'max_files' => 0,

],

// 其它日志通道配置

],

];

path为空,框架应该有默认值啊,然后就一路找到vendor\topthink\think-log\src\log\driver\File.php getMasterLogFile方法

protected function getMasterLogFile(): string

{

if (substr($this->config['path'], -1) != DIRECTORY_SEPARATOR) {

$this->config['path'] .= DIRECTORY_SEPARATOR;

}

.

.

.

卧槽!!! 默认日志保存路径/,然后修改配置文件'path' => app()->getRuntimePath() . '/log',再次刷新重试,运行正常,查看runtime目录,日志已记录进去,然后想到本地windows环境不存在权限问题,打开D盘,果然

php tp6 错误日志接管分析,ThinkPHP6 记录日志 Permission denied 的解决方法

文档里日志处理也没有对path参数特别说明,感觉是个坑!