PHP 7 用户会话问题 - 无法初始化存储模块

Posted

技术标签:

【中文标题】PHP 7 用户会话问题 - 无法初始化存储模块【英文标题】:PHP 7 user sessions issue - Failed to initialize storage module 【发布时间】:2016-03-11 14:23:58 【问题描述】:

php 7.0 中使用各种 PHP 框架会话驱动程序时存在错误。我最初在使用 CodeIgniter 数据库驱动程序时遇到了这个问题,并认为这是一个 CodeIgniter 问题,但后来在多个会话驱动程序和多个框架上遇到了它。在这一点上,我已经安全地得出结论,会话驱动程序的类型无关紧要 - 看似随机,应用程序将崩溃并且日志(我已经尝试过 Apache 和 php-fpm + nginx)填写以下内容:

PHP 致命错误:session_start():初始化存储失败 模块:用户(路径:[我的 php.ini 路径中的任何内容])

我使用的驱动程序不使用 php.ini 中设置的值,无论我是否将 session.save_handler 设置为 php.ini 中的文件、redis 等,也无论我设置的路径如何(Redis 服务器,如果 redis ,启用文件的完全可写文件夹)发生错误。除非在框架外的 php 文件中调用本机“session_start()”,否则永远不应点击此处的路径。此外,在框架之外调用“session_start()”也可以正常工作......所以很明显 PHP 可以访问该路径。就好像在某个时候,会话驱动程序变成了框架驱动程序和 php.ini 中设置的任何内容的混合体。错误消息总是有 session.save_handler 的“用户”,所以显然这不是从 php.ini 中提取的......但路径是。为什么会发生这种情况?这是在您体验之前很难描述的问题之一......而且很难重现,因为即使在数百次会话中一切似乎都可以正常工作(直到它突然停止工作)。重新启动 Apache 也不能解决问题 - 这里有很多问题,我最终只是重新启动机器以避免停机。显然,PHP 7 机器现在将从负载均衡器轮换中退出……但我希望现在能解决问题。

我遇到了我自己编译的 PHP 7.0 RC5、RC6 和 RC8 以及 Ubuntu 15.10 Wily (7.0.0-2+deb.sury.org~wily+1) 上最新的 Ondřej Surý PPA 的问题.我在 CodeIgniter 和 Symfony 上遇到过这个问题,并且无论框架中使用的驱动程序类型(文件、数据库、redis)或 php.ini 中设置的 session.save_handler (同样应该无关紧要)都遇到过这个问题在这里,但只是认为应该提及)。我不断尝试组合并在野外扔东西,这个问题每次都会发生(有时需要 12 多个小时,具体取决于网站的流量)。

感谢您提供的任何帮助!我愿意接受建议并愿意在这一点上尝试任何事情。

【问题讨论】:

您是否在bugs.php.net 上报告了该错误? 只需添加一个正确的路径来存储会话。示例:转到配置文件并替换 $config['sess_save_path'] = NULL;使用 $config['sess_save_path'] = APPPATH 。 '缓存/会话/';不要忘记对缓存文件夹进行 0777 权限。 【参考方案1】:

当会话处理程序的open() 函数没有返回布尔值 TRUE 时会发生此错误,这显然意味着某种失败。

可能是连接数据库失败、打开文件失败、目录不存在等 - 这取决于会话处理程序实际使用的内容。

【讨论】:

这是正确答案。就我而言,我添加了错误的数据库名称。 我同意。这是正确的答复。就我而言,我的服务器的数据库没有工作,但代码点火器给了我与这里讨论的相同的错误。服务器支持一心想让我相信这是您的脚本中的错误。但我证明了数据库已经关闭并且他们意识到了这一点。【参考方案2】:

function _open 应该返回 true 以避免这个错误。

无论我们使用数据库还是文件,它都不能为空或为空。

当我们使用数据库存储会话数据时,我们将其保留为空白或不返回布尔值。这是这个错误的主要原因。

class session_handler

    public function __construct()
    
        session_set_save_handler(
            array($this, "_open"),
            array($this, "_close"),
            array($this, "_read"),
            array($this, "_write"),
            array($this, "_destroy"),
            array($this, "_gc")
        );
    

    public function _open($savePath, $sessionId)
    
        return true;
    

    public function _close()       
    public function _read($id)   
    public function _write($id, $data)   
    public function _destroy($id)   
    public function _gc($max)   

它只适用于 PHP 7。我不知道它是否是一个错误。

【讨论】:

这实际上是一个错误,这在 PHP 5 中并没有发生,只是人们已经习惯了错误的行为,以至于它现在是一个有影响力的 BC 中断,所以他们直到 PHP 7 才修复它。 这也解决了我在 ZF1 上的一个问题。谢谢。 嘿,你能帮我看看你说的是哪个文件吗?我在 codeigniter 中找不到 session_handler 文件 我不认为 SessionHandlerInterface 实现中的函数使用下划线。我认为它们只是没有下划线的“打开”、“关闭”、“写入”等。【参考方案3】:

这通常是由于会话无法连接到它使用的任何驱动程序(文件、数据库)。

我通过查看config.php 文件解决了这个问题

    $config['sess_driver'] = 'database';
    $config['sess_cookie_name'] = 'ci_session';
    $config['sess_expiration'] = 7200;
    $config['sess_save_path'] = 'ci_sessions';
    $config['sess_match_ip'] = FALSE;
    $config['sess_time_to_update'] = 300;
    $config['sess_regenerate_destroy'] = FALSE;

因此,由于我使用了数据库,这意味着它由于某种原因无法连接! (对于文件可能没有写入缓存文件的权限)

接下来我打开了日志

    $config['log_threshold'] = 4;

其中4 = All Messages.. 然后刷新页面,现在我在application/logs 中有一个名为log-#.php 的文件,其中# 是一个日期。

    INFO - 2017-08-30 10:05:41 --> Database Driver Class Initialized
    ERROR - 2017-08-30 10:05:41 --> Severity: Warning --> mysqli::real_connect(): (HY000/1045): Access denied for user 'user'@'localhost' (using password: YES) /var/system/database/drivers/mysqli/mysqli_driver.php 202
    ERROR - 2017-08-30 10:05:41 --> Unable to connect to the database
    ERROR - 2017-08-30 10:05:41 --> Severity: Warning --> mysqli::real_connect(): (HY000/1045): Access denied for user 'user'@'localhost' (using password: YES) var/system/database/drivers/mysqli/mysqli_driver.php 202
    ERROR - 2017-08-30 10:05:41 --> Severity: Error --> session_start(): Failed to initialize storage module: user (path: ci_sessions) /var/system/libraries/Session/Session.php 140

所以我只是确保用户可以访问数据库并且它工作正常。

【讨论】:

只需添加一个正确的路径来存储会话。示例:转到配置文件并替换 $config['sess_save_path'] = NULL;使用 $config['sess_save_path'] = APPPATH 。 '缓存/会话/';不要忘记对缓存文件夹进行 0777 权限。 成功了!谢谢!【参考方案4】:

我决定迁移我的系统并进行一些急需的更新。我使用 Codeigniter 3 和 php 7.2 遇到了这个问题。在我发现这个问题后,我意识到它是多么可笑,并想知道我怎么没有早点弄清楚。 ?

无论如何,至少对我来说这是解决方案。

显然要确保已安装 memcacheD:

sudo apt-get update
sudo apt-get install php7.2-memcached

如果一切顺利,那么我们可以继续检查其他所有内容。

在 Codeigniter 的配置文件“/application/config/config.php”中有一个部分可以指定会话选项:

$config['sess_driver'] = 'memcached';
$config['sess_cookie_name'] = 'some_session_name';
$config['sess_expiration'] = 7200;
$config['sess_save_path'] = NULL;
$config['sess_match_ip'] = FALSE;
$config['sess_time_to_update'] = 300;
$config['sess_regenerate_destroy'] = FALSE;

需要为我更改的行是这一行:

$config['sess_save_path'] = NULL;

确保将其设置为 CI3 手册中记录的有效路径。 正确的设置如下所示:

$config['sess_driver'] = 'memcached';
$config['sess_save_path'] = 'localhost:11211';

确保更改“localhost”以反映您的 memcached 服务器位置。

欲了解更多信息,请参阅 - Codeignier Session Manual

也可以看看这里:php memcacheD Sessions support

如果页面上的评论被删除,我在这里发布:

如果你想使用“memcacheD”扩展而不是“memcache”(有 两个不同的扩展)用于会话控制,您应该付费 注意修改php.ini

谷歌的大多数网络资源都是基于内存缓存的,因为它是 比 memcacheD 更早的版本。他们会说如下

session.save_handler = 内存缓存 session.save_path = "tcp://localhost:11211"

但是当涉及到memcacheD时它是无效的

你应该这样修改 php.ini

session.save_handler = memcached session.save_path = "localhost:11211"

看,没有协议标识符

为了测试,我这样做是为了让用户认为 php 它本身在访问 memcacheD 时没有问题:

session_start();

    header('Content-Type: text/plain');
    session_start();
    if(!isset($_SESSION['visit']))
    
        echo "This is the first time you're visiting this server\n";
        $_SESSION['visit'] = 0;
    
    else
            echo "Your number of visits: ".$_SESSION['visit'] . "\n";

    $_SESSION['visit']++;

    echo "Server IP: ".$_SERVER['SERVER_ADDR'] . "\n";
    echo "Client IP: ".$_SERVER['REMOTE_ADDR'] . "\n";
    print_r($_COOKIE);

$servers = explode(",", ini_get("session.save_path"));
$c = count($servers);
for ($i = 0; $i < $c; ++$i) 
  $servers[$i] = explode(":", $servers[$i]);



$mem = new memcached();

$mem->addServer('127.0.0.1', '11211', '1');
$mem->set('011', 'Hello There');

print_r($mem->get('011'));

print_r($mem->getAllKeys());

这让我看到 memcacheD 工作正常。

在您的 php.ini 中也有一些选项需要注意。只需搜索 [session] 或 session.save_path。 CI3 声明它不使用 php.ini 文件中的此选项,但如果您计划在框架之外使用 memcacheD 并保持一致性,则值得设置。

这从 php.ini 文件中的 ~1327 行开始:

[Session]
; Handler used to store/retrieve data.
; http://php.net/session.save-handler
session.save_handler = memcached

; Argument passed to save_handler.  In the case of files, this is the path
; where data files are stored. Note: Windows users have to change this
; variable in order to use PHP's session functions.
;
; The path can be defined as:
;
;     session.save_path = "N;/path"
;
; where N is an integer.  Instead of storing all the session files in
; /path, what this will do is use subdirectories N-levels deep, and
; store the session data in those directories.  This is useful if
; your OS has problems with many files in one directory and is
; a more efficient layout for servers that handle many sessions.
;
; NOTE 1: PHP will not create this directory structure automatically.
;         You can use the script in the ext/session dir for that purpose.
; NOTE 2: See the section on garbage collection below if you choose to
;         use subdirectories for session storage
;
; The file storage module creates files using mode 600 by default.
; You can change that by using
;
;     session.save_path = "N;MODE;/path"
;
; where MODE is the octal representation of the mode. Note that this
; does not overwrite the process's umask.
; http://php.net/session.save-path
;session.save_path = "/var/lib/php/sessions"
session.save_path = "locahost:11211"

检查设置的另一个地方是 mecacheD 服务器配置文件。根据系统,它的位置可能会有所不同。对我来说,它位于 /etc/ 目录下。

/etc/memcached.conf

图片供参考我遇到的错误:

编辑

如果您使用套接字(即 unix:///some/place/memcached.sock)连接到 Memcached 服务器,则没有关于如何使其工作的确切文档。您只需在配置中执行以下操作:

$config['sess_save_path'] = "/some/place/memcached.sock:11211";

【讨论】:

【参考方案5】:

在我的情况下,我使用 PHP ver 5.6CI ver 3.4 (Codeigniter) 服务器:BIGROCK 我在我的实时服务器中发现了这些问题。

然后过了很久。我只是试图删除我的数据库并重新创建它。

然后只有我知道我没有允许用户访问数据库。

因此,当您完成创建数据库和用户后,您可能应该授予用户访问数据库的权限(previlleges)。

让我知道它是否对您有用。谢谢。

【讨论】:

【参考方案6】:

只需将 /your-Codeigniter-project/system/cache 及其内容的权限更改为 0777 即可。由于缺少权限,它实际上无法创建会话文件。使用以下命令sudo chmod 0777 /your-Codeigniter-project/system/cache sudo chmod 0777 /your-Codeigniter-project/system/cache/* 注意:将上面的“your-Codeigniter-project”替换为您的项目路径。

【讨论】:

【参考方案7】:

1- 使用 phpinfo() 查找默认会话 tmp 文件夹(session.save_path);在 yourdomain.com 上 2 通过 ssh 连接到您的主机 3 转到 tmp 父文件夹 $ cd /home/abc/xyz 4 chmod 777 -R tmp

【讨论】:

【参考方案8】:

它的工作完美。

$config['sess_driver'] = 'files';
$config['sess_cookie_name'] = 'ci_session';
$config['sess_expiration'] = 7200;
$config['sess_save_path'] = sys_get_temp_dir();
$config['sess_match_ip'] = FALSE;
$config['sess_time_to_update'] = 300;
$config['sess_regenerate_destroy'] = FALSE;

【讨论】:

【参考方案9】:

我更改了我的 php.ini:

session.save_path = "N;/path" **to** session.save_path = "/tmp"

然后我重新启动我的 php7-fpm

【讨论】:

我可以在一个普通的 php 文件(框架之外)中发出一个“session_start()”而没有任何问题......所以即使 php.ini 中的配置也可以正常工作。更令人沮丧的是,即使使用框架会话驱动程序,一切都可以正常工作一段时间(直到它没有) - 错误日志从空到相同的错误反复数十次/秒:PHP致命错误: session_start():初始化存储模块失败:用户(路径:tcp://127.0.0.1:6379) 澄清一下,上面的错误是我把php.ini改成使用Redis作为save_handler,对应的位置就是php.ini中设置的位置。但是,在应用程序中使用的实际会话驱动程序不是 Redis ......所以不知何故,在某些时候,会话驱动程序似乎部分恢复为 php.ini 设置。我会继续挖掘 - 谢谢。 出于安全原因,您的session.save_path 不应该对 PHP 以外的任何人写入。 /tmp/ 通常每个人都可以写。【参考方案10】:

我相信我已经解决了这个问题;我将结束这个问题。基本上,当框架会话驱动程序/配置出现问题(超出 sql 连接、Redis 内存不足等问题)时,它会恢复为尝试使用 php.ini 中设置的 sess.save_path,同时仍在使用框架会话驱动程序。所以除非框架驱动与php.ini中默认的sess.save_path兼容,否则就会出现这个错误。对我来说,也恢复到 php.ini 中的 sess.save_handler 会更有意义......但如果这是一个问题,显然需要解决应用程序配置的更大问题。

中断会话的不是这个错误本身......这是框架会话驱动程序的一个潜在问题。我觉得自己很愚蠢……但这些日志基本上让我大吃一惊。重新启动 nginx 或 Apache 无法解决问题,因为问题出在其他地方。我相信可用的 PHP 7 Redis 库仍有一些问题需要解决,SQL 问题是我的错。在看似尝试了多种组合并获得相同结果之后,这个问题显得更加神秘。在 PHP 7 上使用 Redis 会话时我仍然会遇到奇怪的错误,但就像我说的,PHP 7 Redis 库不是很成熟。

【讨论】:

由于您已将其标记为“codeigniter”,因此我认为这就是您在此处谈论的“框架”。在这种情况下,您的结论是不准确的 - CodeIgniter 不会“恢复”使用 sess.save_path;它将它设置为您在配置中放入的内容,并且始终使用它。【参考方案11】:

我们刚刚遇到了一个类似的问题,我们正在使用session_set_save_handler 设置我们自己的自定义处理程序以转到 memcached,但一直收到此错误:

Warning: session_write_close(): Failed to write session data (user). Please verify that the current setting of session.save_path is correct (/var/lib/php/7.0/session) in Unknown on line 0

原来“write”函数需要返回一个布尔值(就像 start 一样),但它是 session_set_save_handler 的唯一函数,在官方 PHP 文档中没有提及任何返回值。因此,虽然看起来它正在恢复到默认会话处理程序,但它只是为默认会话处理程序提供 error

错误和文档页面永远不会让我们找到解决方案...

【讨论】:

【参考方案12】:

仅当 session_save_path 无效时才会发生这种情况,如果您将会话数据存储在数据库中,则必须创建会话表以便 CI 保存数据,否则您将最终出现此错误。希望对某人有所帮助

【讨论】:

【参考方案13】:

我不得不将我的代码点火器升级到最新版本来解决这个问题。

运行时间:

CentoOS: 7.6.1810
Mysql: 8.0.15
PHP: PHP 7.3.4 

我尝试了很多事情,比如将会话从数据库移动到文件和 Memcached。没有任何效果。修复它的唯一方法是从 CI 3.0 升级到 3.1,然后它就像它应该的那样工作。

希望它可以帮助某人。

【讨论】:

【参考方案14】:

此错误是由于未定义的会话路径引起的。 打开 application/config/config.php 行号。 383. 替换以下行$config['sess_save_path'] = NULL;$config['sess_save_path'] = APPPATH . 'cache/session/'; 不要忘记给缓存/会话文件夹写权限。

【讨论】:

以上是关于PHP 7 用户会话问题 - 无法初始化存储模块的主要内容,如果未能解决你的问题,请参考以下文章

PHP存储会话数据,在会话中存储用户ID

php在会话中存储用户ID?

Bref PHP 将会话存储在 redis 中但无法读取

PHP 无法从 NFS 共享读取会话

PHP会话技术

PHP 会话管理