一次laravel权限排错过程

问题

因为是使用vagrant开发,代码目录的挂载情况是这样子的:

~/Documents/dev/meitubar[物理机] <=> /home/wwwroot[vagrant虚拟机]

无论在虚拟里面如何chmod或chown都无法改变app/storage的权限和归属,后面直接用将物理机的目录修改成777,权限终于是变了,但是在Laravel的
app/storage/sessions 里面新生成的文件,照样没有写入权限,表示很无奈。

排查

第一步

首先看下nginx的执行用户是谁

[vagrant@localhost app]$ sudo lsof -i :80
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 4253 root 7u IPv4 19510 0t0 TCP *:http (LISTEN)
nginx 4255 www 7u IPv4 19510 0t0 TCP *:http (LISTEN)
nginx 4256 www 7u IPv4 19510 0t0 TCP *:http (LISTEN)
nginx 4257 www 7u IPv4 19510 0t0 TCP *:http (LISTEN)
nginx 4258 www 7u IPv4 19510 0t0 TCP *:http (LISTEN)
nginx 4259 www 7u IPv4 19510 0t0 TCP *:http (LISTEN)

第一个进程为nginx的Master进程,下面5个为Worker进程
5个Worder进程,可以在nginx.conf里面配置 worker_processes 5; 来调整worker的数量
关于master 与 worder 可以参考初探nginx架构

第二步

看到执行用户是www,再看看app/storages里面的文件权限

[vagrant@localhost sessions]$ ls -ahl
total 12K
drwxrwxrwx 1 vagrant vagrant 170 Jan 2 11:14 .
drwxrwxrwx 1 vagrant vagrant 272 Oct 21 08:14 ..
-rw-r--r-- 1 vagrant vagrant 197 Jan 2 11:14 9c2a6e9d857487da4256d4811a404b6418a5f9b9
-rw-r--r-- 1 vagrant vagrant 248 Jan 2 09:47 d039881bef49b836503ceed0349736829e3f63bb
-rwxrwxrwx 1 vagrant vagrant 13 Jun 2 2014 .gitignore

显示的权限只有vagrant这个用户有写权限,再看nginx是www的执行用户,原先以为是找到问题了,很欣然的在nginx.conf里面使用如下配置
把nginx的执行用户修改成了root

user root root;

重新启动了下nginx,发现木有效果。

第三步

后面才反应过来php脚本是php-fpm 执行的,不是nginx执行的。
可以使用下面三种方法下查看是谁在执行php-fpm

  • 使用 lsof 命令
    同样使用上面的lsof命令来查看,是谁在执行php-fpm
    sudo lsof | grep php-fpm

显示结果如下:

php-fpm 4736 www txt REG 253,0 34998739 12589400 /usr/local/php/sbin/php-fpm
php-fpm 4736 www mem REG 253,0 26060 12585382 /usr/lib64/gconv/gconv-modules.cache
php-fpm 4736 www mem REG 253,0 65928 6029342 /lib64/libnss_files-2.12.so
php-fpm 4736 www mem REG 253,0 10856 12327349 /usr/lib64/libXau.so.6.0.0
php-fpm 4736 www mem REG 253,0 122312 12327393 /usr/lib64/libxcb.so.1.1.0
php-fpm 4736 www mem REG 253,0 165264 6029412 /lib64/libexpat.so.1.5.2
php-fpm 4736 www mem REG 253,0 90880 6029314 /lib64/libgcc_s-4.4.7-20120601.so.1
php-fpm 4736 www mem REG 253,0 55080 12324695 /usr/lib64/libgomp.so.1.0.0
php-fpm 4736 www mem REG 253,0 1297896 12327397 /usr/lib64/libX11.so.6.3.0
php-fpm 4736 www mem REG 253,0 67592 6029396 /lib64/libbz2.so.1.0.4
php-fpm 4736 www mem REG 253,0 220584 12327227 /usr/lib64/libfontconfig.so.1.4.4
php-fpm 4736 www mem REG 253,0 12590976 133461 /usr/local/imagemagick/lib/libMagickCore-6.Q16.so.2.0.0
php-fpm 4736 www mem REG 253,0 2702274 133465 /usr/local/imagemagick/lib/libMagickWand-6.Q16.so.2.0.0

很明显执行用户是:www

  • 使用posix_getpwuid函数来获取
    其实用原生的PHP代码也可以查看是谁在执行某个PHP脚本,代码如下
    $whoExec = posix_getpwuid(posix_geteuid());
    print_r($whoExec);

打印出来的结果是这个样子的

array(7) {
["name"]=> string(3) "www"
["passwd"]=> string(1) "x"
["uid"]=> int(502)
["gid"]=> int(502)
["gecos"]=> string(0) ""
["dir"]=> string(9) "/home/www"
["shell"]=> string(13) "/sbin/nologin"
}

很明显执行用户是:www

  • 查看php-fpm的配置文件
    查看 /usr/local/php/etc/php-fpm.conf 具体内容如下
    [global]
    pid = /usr/local/php/var/run/php-fpm.pid
    error_log = /usr/local/php/var/log/php-fpm.log
    log_level = notice
    [www]
    listen = /tmp/php-cgi.sock
    listen.backlog = -1
    listen.allowed_clients = 127.0.0.1
    listen.owner = www
    listen.group = www
    listen.mode = 0666
    user = www
    group = www
    pm = dynamic
    pm.max_children = 20
    pm.start_servers = 2
    pm.min_spare_servers = 1
    pm.max_spare_servers = 6
    request_terminate_timeout = 100
    request_slowlog_timeout = 0
    slowlog = var/log/slow.log

看到了 listen.owner 和 listen.group 均为 www
再次证明,就是 www 这个用户在执行php-fpm了
因为app/storage/sessions/ 里面生成的文件,所属用户与组均是vagrant,那就很明确的把php-fpm的执行用户改成vagrant

listen.owner = vagrant
listen.group = vagrant
listen.mode = 0666
user = vagrant
group = vagrant

就此搞定,需要说明的是如果不是使用vagrant开发的话,直接修改app/storage为777就可以了,不需要这么折腾。