【问题标题】:php-fpm and nginx session problemsphp-fpm 和 nginx 会话问题
【发布时间】:2021-10-17 04:28:48
【问题描述】:

过去一周左右我一直遇到这个问题。我一直在研究一个严重依赖 Sessions 的 PHP 项目。出于某种原因,我们在过去几天保存会话时遇到了麻烦。知道为什么吗?

这是错误:

Warning: Unknown: open(/tmp/sess_mmd0ru5pl2h2h9bummcu1uu620, O_RDWR) failed: Permission denied (13) in Unknown on line 0 Warning: Unknown: Failed to write session data (files). Please verify that the current setting of session.save_path is correct (/tmp) in Unknown on line 0
Warning: session_start(): open(/tmp/sess_mmd0ru5pl2h2h9bummcu1uu620, O_RDWR) failed: Permission denied (13)

nginx 版本:

nginx version: nginx/1.0.11

PHP-FPM 配置:

;;;;;;;;;;;;;;;;;;;;;
; FPM Configuration ;
;;;;;;;;;;;;;;;;;;;;;

; All relative paths in this configuration file are relative to PHP's install
; prefix.

; Include one or more files. If glob(3) exists, it is used to include a bunch of
; files from a glob(3) pattern. This directive can be used everywhere in the
; file.
include=/etc/php-fpm.d/*.conf

;;;;;;;;;;;;;;;;;;
; Global Options ;
;;;;;;;;;;;;;;;;;;

[global]
; Pid file
; Default Value: none
pid = /var/run/php-fpm/php-fpm.pid

; Error log file
; Default Value: /var/log/php-fpm.log
error_log = /var/log/php-fpm/error.log

; Log level
; Possible Values: alert, error, warning, notice, debug
; Default Value: notice
;log_level = notice

; If this number of child processes exit with SIGSEGV or SIGBUS within the time
; interval set by emergency_restart_interval then FPM will restart. A value
; of '0' means 'Off'.
; Default Value: 0
;emergency_restart_threshold = 0

; Interval of time used by emergency_restart_interval to determine when
; a graceful restart will be initiated.  This can be useful to work around
; accidental corruptions in an accelerator's shared memory.
; Available Units: s(econds), m(inutes), h(ours), or d(ays)
; Default Unit: seconds
; Default Value: 0
;emergency_restart_interval = 0

; Time limit for child processes to wait for a reaction on signals from master.
; Available units: s(econds), m(inutes), h(ours), or d(ays)
; Default Unit: seconds
; Default Value: 0
;process_control_timeout = 0

; Send FPM to background. Set to 'no' to keep FPM in foreground for debugging.
; Default Value: yes
;daemonize = yes

;;;;;;;;;;;;;;;;;;;;
; Pool Definitions ;
;;;;;;;;;;;;;;;;;;;;

; See /etc/php-fpm.d/*.conf

nginx.conf:

#######################################################################
#
# This is the main Nginx configuration file.
#
# More information about the configuration options is available on
#   * the English wiki - http://wiki.nginx.org/Main
#   * the Russian documentation - http://sysoev.ru/nginx/
#
#######################################################################

#----------------------------------------------------------------------
# Main Module - directives that cover basic functionality
#
#   http://wiki.nginx.org/NginxHttpMainModule
#
#----------------------------------------------------------------------

user              nginx nginx;
worker_processes  5;

error_log  /var/log/nginx/error.log;
#error_log  /var/log/nginx/error.log  notice;
#error_log  /var/log/nginx/error.log  info;

pid        /var/run/nginx.pid;


#----------------------------------------------------------------------
# Events Module
#
#   http://wiki.nginx.org/NginxHttpEventsModule
#
#----------------------------------------------------------------------

events {
    worker_connections  4096;
}


#----------------------------------------------------------------------
# HTTP Core Module
#
#   http://wiki.nginx.org/NginxHttpCoreModule
#
#----------------------------------------------------------------------

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

        index index.php index.html index.htm;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    # Load config files from the /etc/nginx/conf.d directory
    # The default server is in conf.d/default.conf
    include /etc/nginx/conf.d/*.conf;
        server {
                listen 80;
                server_name stats.smilingdevil.com;

                error_page   404   /404.php;

                root /var/www;

                access_log /var/log/nginx/access.log;
                error_log /var/log/nginx/error.log;

                location / {
                        set $page_to_view "/index.php";
                        try_files $uri $uri/ @rewrites;
                        root /var/www/;
                        index index.php;
                }

                location @rewrites {
                        if ($uri ~* ^/([a-z0-9]+)$) {
                                set $page_to_view "/$1.php";
                                rewrite ^/([a-z]+)$ /$1.php last;
                        }
                }

                location ~ \.php$ {
                        include /etc/nginx/fastcgi.conf;
                        fastcgi_pass 127.0.0.1:9000;
                        fastcgi_param SCRIPT_FILENAME /var/www$fastcgi_script_name;
                }
        }
}

【问题讨论】:

  • 请检查/tmp目录模式,应该是777。还要检查selinux audit.log(如果已安装)

标签: session nginx php


【解决方案1】:

只需将 /var/lib/php/session/ 的所有权从 apache 更改为 nginx,而不是读取世界。

sudo chown -R nginx:nginx /var/lib/php/session/

【讨论】:

  • 这不起作用。当php 包更新时,权限将被恢复。
  • /var/lib/php/session/ 上的默认所有权通常是 apache - 或 - www-data,因此如果使用 nginx,您应该始终在升级时统计文件夹。我再次建议您将组权限授予 root,将用户授予 nginx。即 chown -R root:nginx /var/lib/php/session/ 而不是 chown -R nginx:nginx /var/lib/php/session/ 正如我之前发布的那样
  • 这不会长期有效。许多包管理器会在任何更新时更改/var/lib/php/session 的权限。在任何更新之后需要额外的手动步骤是未来失败的秘诀。我发现将用户 nginx 添加到 apache 组更容易。查看下一个答案
【解决方案2】:

我发现我的 php.ini 试图将会话保存到 /var/lib/php/session 而不是 /tmp

因此请检查您的 ini 文件并查看它们被保存到的位置(或将其设置到其他位置);然后确保该目录可由适当的进程写入

【讨论】:

  • 为什么有些安装使用/var/lib/php5/有些使用/tmp...等?
  • 是的,我遇到了同样的问题,除了 /var/lib/php/5.5/session。 @CMCDragonkai 我认为它的参数是你在编译时给它的。
  • 注意,当您通过 yum (CentOS) 升级 NginX 时,它默认将 /var/lib/php 的所有权更改为“apache”——所有权错误!这给我带来了麻烦。
  • 这不是 nginxapache 会弄乱会话路径。 php 假设它与导致问题的apache 一起使用。许多人决定“平局”,只使用/tmp 获取会话数据。这是相对不安全的。请参阅我的答案以了解更多详细信息。
  • 对于那些想知道的人,php.ini 参数是session.save_path
【解决方案3】:

TL;DR:将nginx 用户添加到apache

RHEL 已决定 /var/lib/php/sessionphp 包所有。该软件包已决定在安装时始终重新创建 /var/lib/php/session 目录,并将始终将该目录归还给 root 拥有的目录,组设置为 apache,对每个目录具有完全权限,对其他任何内容没有权限。因此,虽然这里建议的许多解决方案都建议更改 /var/lib/php/session 的权限,但这会在未来引起问题。

https://bugzilla.redhat.com/show_bug.cgi?id=1146552

RHEL 建议的解决此问题的方法是在您想要存储它的任何位置创建您自己的会话目录,并根据需要设置权限。未来的 php 更新不会影响那个新位置,一切都应该继续工作。

对我来说效果很好的另一种方法是简单地将nginx 添加到apache 组。

【讨论】:

  • +1 将 nginx 添加到 apache 组,除非您将 apache 和 nginx 作为互不信任的用户运行。这几乎不应该发生。
  • 我将 /etc/nginx/nginx.conf 中的用户属性更新为 apache。它更简单,因为会话文件是 mod 600 apache:apache。
  • @StephenJazdzewski Idk,让 Nginx 以用户 apache 运行对我来说似乎很奇怪。我还没有看到具有该模式的会话文件。我一直是0660
  • 我很想删除 apache 用户/组,因为我不使用 Apache...
  • @Matthew 如果您使用 软件包维护者的规定,您的头痛就会减少。当然,这可能并不理想,但处理你在一年内为自己制造的头痛比忽视它更烦人。无论如何,下一次升级可能会重新创建组......
【解决方案4】:

克里斯·拉特利奇是对的, php 有时会在 /var/lib/php/session/ 目录上保存会话 检查您的 php.ini 文件或 创建具有777权限的目录

mkdir /var/lib/php/session
chmod -R 777 /var/lib/php/session

【讨论】:

  • 这对我有用;升级 CentOS 7 服务器导致此文件夹的权限出错;购物车没有存放物品,用户无法登录,并且无法访问管理站点(尽管正在验证登录信息)。
  • 感谢您的评论,它也解决了我的会话问题。但是在该会话文件夹上设置 777 chmod 是否没有安全问题?提前致谢
  • 我不确定这个解决方案的安全性,而且我也做了同样的事情,但每次服务器重新启动时它似乎都会恢复
  • chown nginx.nginx fpmchown nginx.nginx fpm/sessionchmod 777 session
  • 我有一个问题,我的 Ubuntu16.04/PHP7.1 安装将会话文件保存在 /tmp 中,在重新启动时会被擦除,所以我将会话文件夹更改为 /var/lib/php/sessions,这有效.谢谢。
【解决方案5】:

这个错误是由于运行 php 进程的用户可能没有权限写入 /tmp 目录

为了让所有用户都可以写,请使用此推荐

chmod 777 /tmp

导致同样问题的另一个原因是只读文件系统

如果 /dev/sda1 安装在 /tmp 上,并且由于大量写入,您的文件系统可能会变为只读...

要使其再次可重写,请使用此命令

mount -t ext3 -o rw,remount /dev/sda1 /tmp

【讨论】:

  • 我认为...大多数用户将 /tmp 驱动器安装在单独的卷上...我说“如果”.. 在发布有关 stackoverflow 的任何问题之前,请先检查您的程序代码...
  • @SmilingDevil:投票给那些尽力提供帮助的人有点苛刻,你不觉得吗?
  • 我认为这个答案有点太松散了,Joe 下面的答案是在不打开整个 tmp 文件夹的情况下解决了问题。
  • /tmp 应该被所有用户读写。 (正确的八进制权限是 1777,而不是 0777 - 区别在于“粘性”位,这使得用户 A 无法删除用户 B 的文件。)
【解决方案6】:

似乎我在 Linux 上发现了一些有趣的东西。当某些 PHP 软件尝试读/写会话时,在 chroot php-cgi 中会出现同样的错误。我认为这可能是权限问题,但是在设置 777 并将网络服务器的所有者设置为“/tmp”并将其设置为多个小时后,它发现“/dev”中的“urandom”设备需要工作。只需确保它找到或复制/制作并临时更改权限(仅用于检查然后更改为安全):

chmod 777 /dev/urandom

奇怪的是,在某些 PHP5.x 版本中不需要它,但在某些 PHP7.x 中却需要。

【讨论】:

  • 我不明白。
  • 似乎 PHP 会话文件需要随机生成器设备 /dev/urandom 来生成不同的文件名,因此您的 Web 服务器应该访问 /dev/urandom(在 Linux 系统的服务器上)。没事吧?
  • "chmod 777 /dev/urandom" 在这种情况下可以提供帮助(仅用于检查,然后必须修复权限)
  • 我给了你一个 +1 的见解。
  • 使用 /dev/urandom 是对 PHP 安全性的升级。如果没有足够的熵并且没有硬件 RNG,它可能会损害性能(延迟)。如果你不需要加密级别的哈希,你可以用 ln -s /dev/random /dev/urandom 代替,但是你以后可能会需要它并且忘记你已经把那个hack 放在了适当的位置——所以要小心并做笔记。
【解决方案7】:

我刚刚在 CentOS 上升级了 PHP。我不得不更改 /etc/php-fpm.d/www.conf 并更新 php_value[session.save_path] 变量并将其设置为 /tmp

php_value[session.save_path]    = /tmp

这很好用。 我认为这不会构成安全隐患。

【讨论】:

  • 如果您信任服务器上运行的所有内容,则没有危险。但是信任服务器上的所有内容是一种危险。你不应该这样做。尽可能分隔。当出现问题时,它无法传播。
【解决方案8】:

当您使用 NGINX 并且服务器授予 apache 而不是 nginx 权限时,您可能会收到此错误。

我的解决方法是:

chown -R nginx:nginx /var/lib/php/

使用 chown 可以更改该特定文件夹的所有者,-R 表示它的递归。

【讨论】:

  • 但是,如果 php 包更新,这将不会持续存在。请参阅我的答案以获得持久性修复;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-28
  • 2018-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-01
相关资源
最近更新 更多