session_start挂起

时间:2010-12-02 08:57:07

标签: php session

因为几次我们的服务器在你每次执行session_start时挂起。

出于测试目的,我创建了一个如下所示的脚本:

<?php
session_start();
?>

从控制台调用它会挂起,甚至无法使用ctrl-c停止,只有kill -9可以正常工作。通过Apache调用它也是一样的。 /var/lib/php/session/保持空白但权限绝对正常,www可以写入并且还具有所有父文件夹的读取权限。

根据管理员的说法,服务器上没有进行任何更改,也没有为会话注册特殊代码。服务器是CentOS 4或5,昨天一切都运行良好。我们重新启动了服务器并更新了PHP,但没有任何改变。

我的想法已经用完了,有什么建议吗?

更新

我们通过将项目移动到另一台服务器来解决了这个问题,所以当问题仍然存在于一台服务器上时,不再需要解决方案了。 我会保持这个问题的开放,以防有人对将来遇到类似问题的人有所了解。

12 个答案:

答案 0 :(得分:25)

有很多原因,这里有一些原因:

A. 会话文件可以独占打开。 当文件锁因任何原因未正确释放时,它会导致session_start()无限期地挂起以执行任何未来的脚本。 解决方法:使用session_set_save_handler()并确保write函数使用fopen($file, 'w') instead of fopen($file, 'x')

B。切勿在php.ini文件中使用以下内容(entropie文件为“/dev/random”),这会导致session_start()挂起:

<?php
ini_set("session.entropy_file", "/dev/random");
ini_set("session.entropy_length", "512");
?>

<强>下进行。 session_start()需要一个要写入的目录。

您可以在普通用户帐户中运行Apache plus PHP。然后,Apache当然必须侦听80以外的其他端口(例如,8080)。

请务必执行以下操作: - 创建一个临时目录PREFIX/tmp - 将php.ini放入PREFIX/lib - 编辑php.ini并将session.save_path设置为您刚刚创建的目录

否则,您的脚本似乎会“挂起”session_start()

答案 1 :(得分:5)

如果这有帮助:

在我的场景中,session_start()在Windows上使用PHPStorm(IDE)中的XDebug调试器的同时挂起。我发现有一个明确的原因:每当我从PHPStorm中杀死调试会话时,下次我尝试运行调试会话时,session_start()就会挂起。

如果这是您的方案,那么解决方案是确保每次在IDE中杀死XDebug会话时重新启动Apache。

答案 2 :(得分:3)

我自己有一个奇怪的问题。

我使用的是CentOS 5.5x64,PHP 5.2.10-1。根目录中的一个干净的ANSI文件,除了session_start()之外没有任何内容。会话正在写入磁盘,并且没有抛出任何错误。它只是挂了。

我尝试了Thariama建议的所有内容,并检查了PHP编译设置等。

我的修复:

yum reinstall php;  /etc/init.d/httpd restart

希望这有助于某人。

对于抱怨30秒停机时间不可接受的人来说,这是一个全新的,干净的操作系统安装,而不是正在运行的生产机器上的一个莫名其妙的问题。此解决方案不应在生产环境中使用。

答案 3 :(得分:2)

问题: -

Iv经历(并修复)基于文件的会话挂起请求的问题,并且基于数据库的会话通过存储过时的会话数据(例如以错误的顺序存储每个会话保存)而不同步。

这是由加载会话的任何后续请求(同时请求)引起的,例如ajax,视频嵌入通过php脚本传送视频文件,动态资源文件(如脚本或css)通过php脚本传送等。

在基于文件的会话中,文件锁定会阻止会话写入,从而导致同时请求线程之间出现死锁。

在基于数据库的会话中,要完成的最后一个请求线程将成为最新的保存,因此例如视频传递脚本将在页面请求后很长时间内完成,并用旧会话数据覆盖自更新后的会话。

修复: -

如果您的ajax或资源交付脚本不需要使用会话,那么最简单的方法是从中删除会话使用情况。

否则,您最好自己做一杯咖啡并执行以下操作: -

  1. 根据http://www.php.net//manual/en/class.sessionhandler.php(通过谷歌搜索提供的许多其他示例)编写或使用会话处理程序(如果尚未执行此操作)。
  2. 在会话处理函数write()中加上代码...

        // processes may declare their session as read only ...
        if(!empty($_SESSION['no_session_write'])) {
                unset($_SESSION['no_session_write']);
                return true;
        }
    
  3. 在你的ajax或资源交付php脚本中添加代码(会话启动后)......

        $_SESSION['no_session_write'] = true;
    
  4. 我意识到这应该是一个很小的修复,但不幸的是,如果您需要同时请求每个加载一个会话,那么它是必需的。

    注意如果您的ajax或资源交付脚本确实需要编写/保存数据,那么您需要在会话以外的其他地方执行此操作,例如数据库。

答案 4 :(得分:1)

为那些去香蕉的人提出另一个答案,我有一个session_start()只在特定情况和脚本中死亡。我的会话死亡的原因最终是因为我在一个特别密集的脚本之后存储了很多的数据,最终对session_start()的调用耗尽了&#39; memory_limit&# 39;在php.ini中设置。

增加&#39; memory_limit&#39;后,那些enum次调用不再杀死我的脚本。

答案 5 :(得分:1)

好的我在2台PC上遇到同样的问题,1是MAC mini XAMPP,1是Windows 10 Xampp。 两者都是php花无穷大来运行session_start()。两个PHP版本都是7.x.x

我发现会话文件锁定读写。因此,我添加了代码来使PHP读取会话文件,并在完成

时立即解锁
<?php
session_start([
    'read_and_close' => true,
]);
?>

<?php
//For PHP 5.x
session_start();

session_write_close();
?>

此PHP解锁会话文件=&gt;问题解决

答案 6 :(得分:0)

对我来说,问题似乎来自SeLinux。所需的命令是chcon -R -t httpd_sys_content_t [www目录],以便访问正确的目录。 见https://askubuntu.com/questions/451922/apache-access-denied-because-search-permissions-are-missing

答案 7 :(得分:0)

如果您使用pgAdmin 4,也可能会发生这种情况。

如果您有文件&gt;偏好&gt; SQL编辑器&gt;选项&gt; “自动提交”已禁用,您只是使用查询工具运行查询但未手动提交,则session_start()将冻结。

启用自动提交,或手动提交,或者只关闭pgAdmin,它将不再冻结。

答案 8 :(得分:0)

只需放置session_write_close(); befor Session_start();

如下:

<?php
    session_write_close();
    session_start();
    .....
?>

答案 9 :(得分:0)

就我而言,似乎是 NFS共享锁定了会话,然后重新启动NFS服务器并仅启用了1个Web客户端节点,会话才能正常工作。

答案 10 :(得分:0)

我不知道为什么,但是在 /etc/php/7.4/apache2/php.ini 中更改此值对我有用:

;session.save_path = "/var/lib/php/sessions"
session.save_path = "/tmp"

答案 11 :(得分:0)

还有几分钱可能会对某人有所帮助。就我而言,我将复杂数据存储在 $_SESSION 中,其中包含几个不同的类对象,而 session_start() 无法处理整个反序列化,因为并非每个类都在 session_start 上加载。解决方案是我的情况是在将数据保存到 $_SESSION 之前序列化/jsonify 数据并在我从会话中获取数据后反转该过程。