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

时间:2015-12-07 03:14:43

标签: php codeigniter session fatal-error php-7

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

  

PHP致命错误:session_start():无法初始化存储   module:user(路径:[无论我在php.ini路径中有什么])

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

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

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

13 个答案:

答案 0 :(得分:6)

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

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

答案 1 :(得分:6)

函数_open应返回true以避免此错误。

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

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

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.我不知道它是否是一个bug。

答案 2 :(得分:1)

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

我通过查看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

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

答案 3 :(得分:1)

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

然后很久以后。我只是想删除我的数据库并重新创建它。

然后我才知道我没有权限用户访问数据库。

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

让我知道你的情况是否有用。谢谢。

答案 4 :(得分:0)

我改变了我的php.ini:

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

然后我重启我的php7-fpm

答案 5 :(得分:0)

我相信我已经弄明白了这个问题;我将结束这个问题。基本上,似乎当框架会话驱动程序/配置发生问题(超出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库还不是很成熟。

答案 6 :(得分:0)

我们遇到了类似的问题,我们使用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

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

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

答案 7 :(得分:0)

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

答案 8 :(得分:0)

我决定迁移系统并进行一些非常需要的更新。我使用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”以反映您的内存缓存服务器位置。

有关更多信息,请参见-Codeignier Session Manual

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

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

  

如果您想使用'memcacheD'扩展而不是'memcache'(有   两个不同的扩展)以进行会话控制,您应该支付   注意修改php.ini

     

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

     

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

     

但是对于memcacheD来说无效

     

您应该像这样修改php.ini

     

session.save_handler =内存缓存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

图片供我参考:

Image of Errors

答案 9 :(得分:0)

我必须将代码点火器升级到最新版本才能解决此问题。

运行:

CentoOS: 7.6.1810
Mysql: 8.0.15
PHP: PHP 7.3.4 

我尝试了很多操作,例如将会话从数据库移动到文件和Memcached。没事。修复它的唯一一件事就是从CI 3.0到3.1,然后像预期的那样蓬勃发展。

希望它可以帮助某人。

答案 10 :(得分:0)

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

答案 11 :(得分:0)

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

答案 12 :(得分:0)

此错误是由于未定义的会话路径引起的。
打开 application/config/config.php 行号。 383.
替换下面的行
$config['sess_save_path'] = NULL;

$config['sess_save_path'] = APPPATH . 'cache/session/';
不要忘记授予缓存/会话文件夹的写入权限。