PHP 7 用户会话问题 - 无法初始化存储模块
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34125849/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PHP 7 user sessions issue - Failed to initialize storage module
提问by DrBlueSpruce
A bug exists when using various PHP framework session drivers with PHP 7.0. I initially experienced this issue while using the CodeIgniter database driver and assumed it was a CodeIgniter issue but have since experienced it on multiple sessions drivers and multiple frameworks. At this point I have safely concluded that the type of session driver is irrelevant - seemingly at random, the application will crash and the logs (I've tried both Apache and php-fpm + nginx) fill up with the following:
在 PHP 7.0 中使用各种 PHP 框架会话驱动程序时存在错误。我最初在使用 CodeIgniter 数据库驱动程序时遇到了这个问题,并认为这是一个 CodeIgniter 问题,但后来在多个会话驱动程序和多个框架上遇到了这个问题。在这一点上,我已经安全地得出结论,会话驱动程序的类型无关紧要 - 看似随机,应用程序将崩溃并且日志(我已经尝试了 Apache 和 php-fpm + nginx)填充以下内容:
PHP Fatal error: session_start(): Failed to initialize storage module: user (path: [whatever I have in my php.ini path])
PHP 致命错误:session_start():无法初始化存储模块:用户(路径:[我的 php.ini 路径中的任何内容])
The drivers I am using do not use the values set in php.ini and regardless of whether I set the session.save_handler to files, redis, etc in php.ini and regardless of the path I set (Redis server if redis, fully-writable folder with files enabled) the errors occur. The path here should never be hit unless a native "session_start()" is called in a php file outside of the framework. Also, calling "session_start()" outside of the framework works fine... so clearly PHP can access the path. It's as if at some point, the sessions driver becomes a hybrid of the framework driver and whatever is set in php.ini. The error message always has "user" for the session.save_handler so obviously that's not being pulled from php.ini... but the path is. Why would this be happening? This is one of those issues that is difficult to describe until you have experienced it... and it's difficult to reproduce because everything seems to work fine even for hundreds of sessions (until it suddenly stops working). Restarting Apache does not correct the issue either - there are a number of issues at play here and I end up just rebooting the machine to avoid the downtime. Obviously the PHP 7 machine will be pulled out of the load balancer rotation now... but I was hoping to have things figured out by now.
我使用的驱动程序不使用 php.ini 中设置的值,无论我是否在 php.ini 中将 session.save_handler 设置为文件、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 机器现在将从负载平衡器轮换中拉出......但我希望现在能解决问题。
I have experienced the issue with PHP 7.0 RC5, RC6, & RC8 compiled on my own as well as the latest Ond?ej Sury PPA on Ubuntu 15.10 Wily (7.0.0-2+deb.sury.org~wily+1). I have experienced the issue on CodeIgniter & Symfony, and have experienced the issue regardless of the type of driver used in the framework (files, database, redis) or the session.save_handler set in php.ini (which, again, should be irrelevant here but just thought it should be mentioned). I keep trying combinations and throwing things out in the wild and this issue happens every single time (sometimes it takes 12+ hours depending on the traffic to the website).
我在自己编译的 PHP 7.0 RC5、RC6 和 RC8 以及 Ubuntu 15.10 Wily (7.0.0-2+deb.sury.org~wily+1) 上最新的 Ond?ej Sury PPA 中遇到了这个问题。我在 CodeIgniter 和 Symfony 上遇到过这个问题,并且无论框架中使用的驱动程序类型(文件、数据库、redis)或 php.ini 中设置的 session.save_handler(同样应该无关紧要)都遇到过这个问题在这里,但只是认为应该提到它)。我一直在尝试组合并在野外扔东西,这个问题每次都会发生(有时需要 12 多个小时,具体取决于网站的流量)。
Thanks for any help you can provide! I'm open to suggestions and willing to try anything at this point.
感谢您的任何帮助,您可以提供!我愿意接受建议,并愿意在这一点上尝试任何事情。
回答by Narf
This error occurs when the open()
function of the session handler doesn't return boolean TRUE, which obviously means some kind of failure.
当open()
会话处理程序的函数没有返回布尔值 TRUE时会发生此错误,这显然意味着某种失败。
It could be failure to connect to a database, failure to open a file, a non-existent directory, etc. - that depends on what the session handler actually uses.
可能是连接数据库失败、打开文件失败、目录不存在等 - 这取决于会话处理程序实际使用的内容。
回答by Moin Uddin
function _open should return true to avoid this error.
函数 _open 应返回 true 以避免此错误。
It can not be null or empty whatever we use either database or file.
无论我们使用数据库还是文件,它都不能为 null 或为空。
When we use database to store session data, we keep it blank or no Boolean return. that is the main reason for this error.
当我们使用数据库存储会话数据时,我们将其留空或不返回布尔值。这是这个错误的主要原因。
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) { }
}
It is only for PHP 7. I do not know it is a bug or not.
它仅适用于 PHP 7。我不知道它是否是一个错误。
回答by Saln3t
This is usually is due to the session not being able to connect to whichever driver it uses (file, database).
这通常是由于会话无法连接到它使用的任何驱动程序(文件、数据库)。
I resolved the issue by looking at the config.php
file
我通过查看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;
So since I used a database it means that it doesn't connect for some reason! (For files probably it doesn't have the permission to write the cached files )
因此,由于我使用了数据库,这意味着它由于某种原因无法连接!(对于文件,它可能没有写入缓存文件的权限)
Next I turned on the log
接下来我打开日志
$config['log_threshold'] = 4;
Where 4 = All Messages
.. Then refresh the page, and now I have in application/logs
a file called log-#.php
where #
is a date.
Where 4 = All Messages
.. 然后刷新页面,现在我在application/logs
一个名为log-#.php
where #
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
So I just make sure that the user can access the database and it worked.
所以我只是确保用户可以访问数据库并且它工作正常。
回答by Silambarasan R.D
In my case I'm using PHP ver 5.6
with CI ver 3.4
(Codeigniter)
Server: BIGROCK
I found these problems in my live server.
就我而言,我使用的PHP ver 5.6
是CI ver 3.4
(Codeigniter)服务器:BIGROCK
我在我的实时服务器中发现了这些问题。
Then after long time. I just tried to delete my Database and re Create it.
然后过了很久。我只是试图删除我的数据库并重新创建它。
Then only I went know that I didn't give permissionThe User to Access the Database.
然后只有我才知道我没有授予用户访问数据库的权限。
So When you have finished Creating your Database and User, You should probably give permissions ( previlleges ) to the user to access the Database.
因此,当您完成创建数据库和用户后,您可能应该授予用户访问数据库的权限( previlleges )。
Let me know if it useful in your case. Thank you.
让我知道它对您的情况是否有用。谢谢你。
回答by Kyle Coots
I decided to migrate my system and do some much-needed updating. I ran into this issue using Codeigniter 3 and php 7.2. After I found the issue I realized how ridiculous it was and wonder how I didn't figure it out sooner.
我决定迁移我的系统并进行一些急需的更新。我使用 Codeigniter 3 和 php 7.2 遇到了这个问题。在我发现这个问题后,我意识到它是多么荒谬,并想知道我怎么没有早点弄明白。
Anyway here is the solution at least for me.
无论如何,这里至少对我来说是解决方案。
Obviously make sure memcacheD is installed:
显然确保安装了 memcacheD:
sudo apt-get update
sudo apt-get install php7.2-memcached
If that is good to go then we can proceed to check everything else.
如果这一切顺利,那么我们可以继续检查其他一切。
In Codeigniter's config file "/application/config/config.php" there is a section to to specify session options:
在 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;
The line that needed to be changed for me was this line:
我需要更改的行是这一行:
$config['sess_save_path'] = NULL;
Make sure you set this to a valid path as documented in CI3's manual. The correct setting will look like this:
确保将其设置为 CI3 手册中记录的有效路径。正确的设置如下所示:
$config['sess_driver'] = 'memcached';
$config['sess_save_path'] = 'localhost:11211';
Make sure you change "localhost" to reflect your memcached servers location.
确保更改“localhost”以反映您的 memcached 服务器位置。
For more info see - Codeignier Session Manual
有关更多信息,请参阅 - Codeignier 会话手册
Also have a look here: php memcacheD Sessions support
也看看这里:php memcacheD Sessions support
In case the comment on the page is removed I am posting here:
如果页面上的评论被删除,我在这里发布:
If you want to use 'memcacheD' extention not 'memcache' (there are two diffrent extentions) for session control, you should pay attention to modify php.ini
Most web resource from google is based on memcache because It's earlier version than memcacheD. They will say as following
session.save_handler = memcache session.save_path = "tcp://localhost:11211"
But it's not valid when it comes to memcacheD
you should modify php.ini like that
session.save_handler = memcached session.save_path = "localhost:11211"
Look, there is no protocol indentifier
如果你想使用'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"
看,没有协议标识符
For testing I did this to make user that php it's self wasn't having an issue accessing memcacheD:
为了测试,我这样做是为了让用户认为 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());
This allowed me to see that memcacheD was working ok.
这让我看到 memcacheD 工作正常。
Also in your php.ini there are some options to look out for. Just search for [session] or session.save_path. CI3 stated it doesn't use this option from the php.ini file, but it's prob worth setting if you plan to use memcacheD outside the framework and for consistency.
此外,在您的 php.ini 中还有一些选项需要注意。只需搜索 [session] 或 session.save_path。CI3 表示它不使用 php.ini 文件中的这个选项,但是如果你打算在框架之外使用 memcacheD 并保持一致性,那么它是值得设置的。
This starts around line ~1327 in the php.ini file:
这从 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"
One other place to check settings is the mecacheD server config file. Depending on the system it's location may vary. For me, it was located under the /etc/directory.
另一个检查设置的地方是 mecacheD 服务器配置文件。根据系统,它的位置可能会有所不同。对我来说,它位于/etc/目录下。
/etc/memcached.conf
Image for reference to the errors I was getting:
参考我得到的错误的图像:
EDIT
编辑
If you are using socket i.e. unix:///some/place/memcached.sock to connect to Memcached server it's not documented on exactly how to make this work. You simply do the following in your config:
如果您使用套接字即 unix:///some/place/memcached.sock 连接到 Memcached 服务器,则没有详细说明如何进行此工作。您只需在配置中执行以下操作:
$config['sess_save_path'] = "/some/place/memcached.sock:11211";
回答by jbrahy
I had to upgrade my code ignitor to the latest version to solve this problem.
我不得不将我的代码点火器升级到最新版本来解决这个问题。
Running on:
继续运行:
CentoOS: 7.6.1810
Mysql: 8.0.15
PHP: PHP 7.3.4
I tried a lot of things like moving the session from the database to files and Memcached. Nothing worked. The only thing that fixed it was going from CI 3.0 to 3.1 and boom it just worked like it was supposed to.
我尝试了很多事情,比如将会话从数据库移动到文件和 Memcached。没有任何效果。唯一修复它的是从 CI 3.0 到 3.1 并且繁荣它就像它应该的那样工作。
Hope it helps someone.
希望它可以帮助某人。
回答by Abhilash
Just changed the permissions of /your-Codeigniter-project/system/cache and its contents to 0777 and it worked. It's actually unable to create the session files due to missing permissions. Use the following command sudo chmod 0777 /your-Codeigniter-project/system/cache
sudo chmod 0777 /your-Codeigniter-project/system/cache/*
Note: Replace 'your-Codeigniter-project' above with your project path.
刚刚将 /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”替换为您的项目路径。
回答by Umut Surmeli
1- Find default session tmp folder (session.save_path) with phpinfo(); on yourdomain.com 2 connect to your host via ssh 3 go to tmp parent folder $ cd /home/abc/xyz 4 chmod 777 -R tmp
1- 使用 phpinfo() 查找默认会话 tmp 文件夹(session.save_path);在 yourdomain.com 上 2 通过 ssh 连接到您的主机 3 转到 tmp 父文件夹 $ cd /home/abc/xyz 4 chmod 777 -R tmp
回答by ahamilton9
We just ran into a similar issue, where we were setting our own custom handler with session_set_save_handler
to go to memcached, but kept getting this error:
我们刚刚遇到了类似的问题,我们正在设置我们自己的自定义处理程序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
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
Turns out that the "write" function needs to return a boolean value (just like start), but it's the only function for session_set_save_handler that doesn't mention any return values in the official PHP docs. So while it looks like it's reverting to the default session handler, it's just giving the errorfor the default session handler.
事实证明,“write”函数需要返回一个布尔值(就像 start 一样),但它是 session_set_save_handler 的唯一函数,在官方 PHP 文档中没有提到任何返回值。因此,虽然看起来它正在恢复到默认会话处理程序,但它只是为默认会话处理程序提供错误。
The error nor the doc pages would never have led us to a solution...
错误和文档页面永远不会让我们找到解决方案......
回答by Joseph Daudi
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
仅当 session_save_path 无效时才会发生这种情况,如果您将会话数据存储在数据库中,则必须创建会话表,以便 CI 保存数据,否则最终会出现此错误。希望对某人有所帮助