PHP - ini_set('session.gc_maxlifetime', 5) - 为什么它不结束会话?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3428153/
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 - ini_set('session.gc_maxlifetime', 5) - Why it doesn't end the session?
提问by q0987
The PHP script is as follows:
PHP脚本如下:
<?php // continue.php
ini_set('session.gc_maxlifetime', 5);
session_start();
echo ini_get('session.gc_maxlifetime');
// wait for 7 seconds
usleep(7000000);
if (isset($_SESSION['username']))
{
$username = $_SESSION['username'];
$password = $_SESSION['password'];
$forename = $_SESSION['forename'];
$surname = $_SESSION['surname'];
echo "Welcome back $forename.<br />
Your full name is $forename $surname.<br />
Your username is '$username'
and your password is '$password'.";
}
else echo "Please <a href=authenticate2.php>click here</a> to log in.";
?>
Based on the timeout (i.e. 5 seconds), the script should not print out anything. However, I still receive the following message
根据超时(即 5 秒),脚本不应打印任何内容。但是,我仍然收到以下消息
5Welcome back Bill. Your full name is Bill Smith. Your username is 'bsmith' and your password is 'mysecret'.
It seems that the line ini_set('session.gc_maxlifetime', 5) doesn't work as it should be. I am using windowsXP + XAMMP.
看来 ini_set('session.gc_maxlifetime', 5) 行不能正常工作。我正在使用 windowsXP + XAMMP。
May you tell me how to make it work?
你能告诉我如何使它工作吗?
Thank you
谢谢
回答by Marc B
Even if the garbage collector kicked in and deleted the session file you opened/read with session_start()
, it will NOT reach into the guts of that particular PHP process and delete the $_SESSION
object array.
即使垃圾收集器启动并删除了您打开/读取的会话文件session_start()
,它也不会进入该特定 PHP 进程的内部并删除$_SESSION
对象数组。
Assuming you're on the standard file-based session handler (which contains a serialize()
'd copy of $_SESSION
), here's what happens.
假设您使用标准的基于文件的会话处理程序(其中包含serialize()
'd 副本$_SESSION
),这就是会发生的情况。
- The session file sits in its temp directory
- You
session_start()
, causing PHP to open/lock the file, read its contents, deserialize the data, and incidentally, possibly update the session file's "last used" timestamp (atime on Unix boxes). - If the stars and moon are aligned correctly with Neptune ascendant in the fifth house, the session garbage collector MAYfire up and delete old session files.
- The garbage collector will happily iterate through the session directory, and delete any files which are older than the max_liftime, BUT WILL NOT DELETE ANY FILES CURRENTLY OPEN/IN USE. Since you've not closed()'d your session, your session's file is still in use, so will not get deleted.
- 会话文件位于其临时目录中
- 你
session_start()
,导致 PHP 打开/锁定文件,读取其内容,反序列化数据,顺便说一下,可能更新会话文件的“上次使用”时间戳(Unix 机器上的时间)。 - 如果星星和月亮与第五宫的上升海王星正确对齐,会话垃圾收集器可能会启动并删除旧的会话文件。
- 垃圾收集器将愉快地遍历会话目录,并删除任何早于 max_lifttime 的文件,但不会删除任何当前打开/使用中的文件。由于您尚未关闭()会话,您的会话文件仍在使用中,因此不会被删除。
Now, if you did something like this:
现在,如果你做了这样的事情:
ini_set(...); // set GC probability to max, short session lifetime, etc...
session_start(); // populate $_SESSION
session_write_close(); // dump $_SESSION out to file, close file, release lock.
sleep(7); // Sleep for 7 seconds;
session_start(); // re-populate $_SESSION;
Now you might just end up with a fresh blank $_SESSION, IFthe garbage collector decides to kick in. However, unless you do that second session_start()
, the old $_SESSION data from the previous start() call WILL STILL BE PRESENT. The session file may have been trashed, but the garbage collector will not touch what's present in your script's memory as it runs.
现在,如果垃圾收集器决定启动,您可能最终会得到一个新的空白 $_SESSION 。但是,除非您这样做,否则session_start()
之前 start() 调用中的旧 $_SESSION 数据仍将存在。会话文件可能已被删除,但垃圾收集器在运行时不会触及脚本内存中的内容。
回答by Mark Baker
session.gc_maxlifetime is the number of seconds after which the session will be consideredfor garbage collection.
session.gc_maxlifetime 是会话将被考虑进行垃圾收集之前的秒数。
session.gc_probability and session.gc_divisor then determine the probability that garbage collection will be executed on any session initialization
session.gc_probability 和 session.gc_divisor 然后确定在任何会话初始化时执行垃圾收集的概率
回答by Artefacto
Read the manual(emphasis mine):
阅读手册(强调我的):
session.gc_maxlifetime
specifies the number of seconds after which data will be seen as 'garbage' and potentiallycleaned up. Garbage collection may occur during session start (depending onsession.gc_probability
andsession.gc_divisor
).
session.gc_maxlifetime
指定数据将被视为“垃圾”并可能被清理的秒数。会话开始期间可能会发生垃圾收集(取决于session.gc_probability
和session.gc_divisor
)。
In the same page:
在同一页面中:
session.gc_divisor
coupled withsession.gc_probability
defines the probability that the gc (garbage collection) process is started on every session initialization. The probability is calculated by usinggc_probability/gc_divisor
, e.g. 1/100 means there is a 1% chance that the GC process starts on each request.session.gc_divisor
defaults to 100.
session.gc_divisor
加上session.gc_probability
定义了在每次会话初始化时启动 gc(垃圾收集)进程的概率。概率是通过使用 来计算的gc_probability/gc_divisor
,例如 1/100 意味着有 1% 的机会在每个请求上启动 GC 过程。session.gc_divisor
默认为 100。
Now do the math and see that it's not very likely the GC will be called on each request.
现在计算一下,不太可能在每个请求上都调用 GC。
You should store the in the session a variable that saves the time of the last activity of the user and use that instead of the session is logically "active". Don't rely on garbage collection.
您应该在会话中存储一个变量,用于保存用户最后一次活动的时间,并使用该变量代替逻辑上“活动”的会话。不要依赖垃圾收集。
回答by Pekka
I don't think this is how gc_maxlifetime
is supposed to work. The manual says
我不认为这gc_maxlifetime
是应该的工作方式。手册上说
session.gc_maxlifetime specifies the number of seconds after which data will be seen as 'garbage' and potentiallycleaned up.
session.gc_maxlifetime 指定数据将被视为“垃圾”并可能被清理的秒数。
(emphasis mine)
(强调我的)
in your case, the session is still active. Therefore, I don't think it will be subject to garbage collection.
在您的情况下,会话仍处于活动状态。因此,我认为它不会受到垃圾收集的影响。
You could try doing a session_write_close()
before the sleep(). That might increase the probability that the garbage collector.
你可以尝试session_write_close()
在 sleep() 之前做一个 。那可能会增加垃圾收集器的概率。