7

在 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 机器现在将从负载均衡器轮换中退出......但我希望现在能解决问题。重新启动 Apache 也不能解决问题 - 这里有很多问题,我最终只是重新启动机器以避免停机。显然,PHP 7 机器现在将从负载均衡器轮换中退出......但我希望现在能解决问题。重新启动 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 多个小时,具体取决于网站的流量)。

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

4

14 回答 14

7

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

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

于 2015-12-08T14:33:19.003 回答
6

函数 _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。我不知道这是否是一个错误。

于 2016-02-16T11:07:07.673 回答
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;

Where 4 = All Messages.. 然后刷新页面,现在我在application/logs一个名为log-#.phpwhere #is a date 的文件中。

    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

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

于 2017-08-30T16:24:44.777 回答
2

我决定迁移我的系统并进行一些急需的更新。我使用 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 会话手册

也看看这里:php memcacheD Sessions support

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

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

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

session.save_handler = memcache 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";
于 2018-08-19T17:28:24.907 回答
1

只需将 /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”替换为您的项目路径。

于 2019-08-26T07:33:56.787 回答
1

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

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

然后只有我知道我没有授予用户访问数据库的权限。

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

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

于 2017-11-09T07:39:15.317 回答
1

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

于 2020-05-17T11:34:22.777 回答
1

它的工作完美。

$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;
于 2021-08-23T07:52:28.757 回答
0

This happens only if the session_save_path is not valid, if you are storing your session data in a database then the session table must be created so that CI saves the data else you will end up with this error. Hope helped someone

于 2017-05-07T09:12:28.487 回答
0

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

运行:

CentoOS: 7.6.1810
Mysql: 8.0.15
PHP: PHP 7.3.4 

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

希望它可以帮助某人。

于 2019-04-25T20:26:36.230 回答
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

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

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

于 2017-04-21T20:14:58.397 回答
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 库不是很成熟。

于 2015-12-07T23:20:57.723 回答
0

此错误是由于未定义的会话路径引起的。
打开 application/config/config.php 行号。383.
将下面的行替换为
$config['sess_save_path'] = NULL;
Do
$config['sess_save_path'] = APPPATH . 'cache/session/';
n't forget to give write permission to cache/session 文件夹。

于 2021-06-28T11:08:33.487 回答
0

我改变了我的 php.ini:

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

我重新启动我的 php7-fpm

于 2015-12-07T04:43:21.930 回答