【问题标题】:Permission denied - nginx and uwsgi socket权限被拒绝 - nginx 和 uwsgi 套接字
【发布时间】:2014-03-31 01:39:41
【问题描述】:

嗯,我目前正在尝试使用 nginx 和 uwsgi 提供我的 django 应用程序。我目前正在使用安装了 uwsgi 的虚拟环境。但是,我目前在尝试访问该页面时收到 502 bad gateway 错误。

我遇到的错误。

2014/02/27 14:20:48 [crit] 29947#0: *20 connect() to unix:///tmp/uwsgi.sock failed (13: Permission denied) while connecting to upstream, client: 144.136.65.176, server: domainname.com.au, request: "GET /favicon.ico HTTP/1.1", upstream: "uwsgi://unix:///tmp/uwsgi.sock:", host: "www.domainname.com.au"

这是我的 nginx.conf

    # mysite_nginx.conf

# the upstream component nginx needs to connect to
upstream django {
    server unix:///tmp/uwsgi.sock; # for a file socket
    #server 127.0.0.1:8001; # for a web port socket (we'll use this first)
}

# configuration of the server
server {
    # the port your site will be served on
    listen      80;
    # the domain name it will serve for
    server_name .domainname.com.au; # substitute your machine's IP address or FQDN
    charset     utf-8;

    # max upload size
    client_max_body_size 75M;   # adjust to taste

    # Django media
    location /media  {
        alias /home/deepc/media;  # your Django project's media files - amend as required
    }

    location /static {
        alias /home/deepc/static; # your Django project's static files - amend as required
    }

    # Finally, send all non-media requests to the Django server.
    location / {
        uwsgi_pass  django;
        include     /home/deepc/.virtualenvs/dcwebproj/dcweb/uwsgi_params; # the uwsgi_params file you installed
    }
}

这是我的 uwsgi.ini 文件

[uwsgi]
socket=/tmp/uwsgi.sock
chmod-socket=644
uid = www-data
gid = www-data

chdir=/home/deepc/.virtualenvs/dcwebproj/dcweb
module=dcweb.wsgi:application
pidfile=/home/deepc/.virtualenvs/dcwebproj/dcweb.pid
vacuum=true

从我在谷歌上读到的内容来看,它是 www-data 组和 /tmp/ 目录的权限问题。但是我对此并不陌生,并试图更改文件夹的权限级别无济于事。有人能指出我正确的方向吗?这是权限问题吗?

也可以把sock文件放到tmp目录下吗?

谢谢

【问题讨论】:

  • 尝试将chmod-socket=644 更改为666?我不确定
  • 原因是nginx无法访问sock文件。确保启动 uwsgi 的用户组与 nginx 组(默认 www-data)相同,以便 nginx 可以访问 sock 文件,然后一切正常。 usermod -g www-data username。希望有帮助

标签: django ubuntu nginx uwsgi


【解决方案1】:

我认为您只需将您的套接字文件更改为 666(664 可以使用 www-data),或者将其删除并再次运行 uwsgi 服务器。

在我的 uwsgi.ini 中:

chmod-socket = 664
uid = www-data
gid = www-data

【讨论】:

  • 我已经设置了这个,并且还尝试使用二进制文件上的标志(--uid www-data --gid www-data),但它似乎忽略了它们。知道为什么吗?
  • @Chockomonkey,您是否在命令行中运行了您的 uwsgi(使用 --uid www-data --gid www-data)?它将仅与您当前的用户一起开始进程。在我的项目中,我只是关注uwsgi-docs.readthedocs.org/en/latest/Upstart.html,init 脚本会将我的 uwsgi 作为服务器运行,进程/socket/pid 上的用户将是 www-data。如果有不清楚的地方请告诉我,谢谢。
  • 感谢您的澄清。你是对的,当我通过命令行运行它时,它会忽略 --uid 和 --gid 标志。所以至少那部分现在是有道理的,耶!但是,我仍然无法让 Emperor 与 Upstart 一起正常运行。见stackoverflow.com/questions/29243445/…
  • 您先生,是一位绅士,也是一位学者。我必须在我的 uwsgi.ini 文件中添加 uid/gid 标志。
  • 多么传奇,谢谢!调试此类问题的最佳方法是什么?这不像 nginx 在其日志中抱怨缺少权限..
【解决方案2】:

哇,这个问题几乎花了我一整天的时间!

我用uwsgi 2.0.14, nginx 1.10.1, django 1.10

综上所述,最重要的是确保以下两个用户都拥有rwxsocket文件的权限:

  1. nginx的用户;
  2. uWSGI的用户;

所以,你可以一一检查。


首先你可以通过刷新 url 来检查 web 服务器nginx 是否有权限,比如http://192.168.201.210:8024/morning/,而不运行 uwsgi。如果你看到/var/log/nginx/error.log没有这样的文件或目录,像这样:

2016/10/14 16:53:49 [crit] 17099#0: *19 connect() to unix:///usr/share/nginx/html/test/helloworld.sock failed (2: No such file or directory) while connecting to upstream, client: 192.168.201.140, server: belter-tuesday.com, request: "GET /morning/ HTTP/1.1", upstream: "uwsgi://unix:///usr/share/nginx/html/test/helloworld.sock:", host: "192.168.201.210:8024"

只需创建一个名为helloworld.sock的文件,然后刷新url并再次检查日志文件,如果您在日志文件中看到Permission denied,如下所示:

2016/10/14 17:00:45 [crit] 17099#0: *22 connect() to unix:///usr/share/nginx/html/test/helloworld.sock failed (13: Permission denied) while connecting to upstream, client: 192.168.201.140, server: belter-tuesday.com, request: "GET /morning/ HTTP/1.1", upstream: "uwsgi://unix:///usr/share/nginx/html/test/helloworld.sock:", host: "192.168.201.210:8024"

这意味着网络服务器nginx 没有读取、写入和执行的所有权限。所以你可以授予这个文件的权限:

sudo chmod 0777 helloworld.sock

然后,刷新 url 并再次检查日志文件,如果您看到 Connection denied 在日志文件中,如下所示:

2016/10/14 17:09:28 [error] 17099#0: *25 connect() to unix:///usr/share/nginx/html/test/helloworld.sock failed (111: Connection refused) while connecting to upstream, client: 192.168.201.140, server: belter-tuesday.com, request: "GET /morning/ HTTP/1.1", upstream: "uwsgi://unix:///usr/share/nginx/html/test/helloworld.sock:", host: "192.168.201.210:8024"

这是一个好兆头,这意味着您的网络服务器nginx 从现在开始有权使用helloworld.sock 文件。


接下来运行uwsgi并检查uwsgi的用户是否有使用helloworld.sock的权限。首先,删除我们之前创建的文件helloworld.sock

运行uwsgi:uwsgi --socket /usr/share/nginx/html/test/helloworld.sock --wsgi-file wsgi.py

如果您看到 bind(): Permission denied [core/socket.c line 230],则表示uwsgi 没有权限绑定helloworld.sock。这是test目录的问题,helloworld.sock的父目录。

sudo chmod 0777 test/

现在,您可以成功运行uwsgi

但也许你还看到502 Bad Gateway,太可怕了,我看了一整天。如果您再次检查error.log 文件,您将再次看到:

2016/10/14 17:33:00 [crit] 17099#0: *28 connect() to unix:///usr/share/nginx/html/test/helloworld.sock failed (13: Permission denied) while connecting to upstream, client: 192.168.201.140, server: belter-tuesday.com, request: "GET /morning/ HTTP/1.1", upstream: "uwsgi://unix:///usr/share/nginx/html/test/helloworld.sock:", host: "192.168.201.210:8024"

怎么了???

查看helloworld.sock文件的详细信息,可以看到:

srwxr-xr-x. 1 belter mslab       0 Oct 14 17:32 helloworld.sock

uWSGI 自动授予此文件755 权限。

您可以通过添加--chmod-socket来更改它:

uwsgi --socket /usr/share/nginx/html/test/helloworld.sock --wsgi-file wsgi.py --chmod-socket=777

好的!最后可以看到:


带走消息

  1. uwsgi_params 文件的位置并不重要;
  2. 由于我的nginx用户和uwsgi用户不一样,甚至不在同一个组,所以我需要给777权限helloworld.sock及其父目录test/
  3. 如果您将helloworld.sock 文件放在您的主目录中,您将始终得到Permission denied
  4. 有两个地方需要设置socket文件路径,一个在nginx conf文件中,对我来说是helloworld_nginx.conf;运行 uwsgi 时的一个。
  5. 检查 SELinux

这是我的helloworld_nginx.conf 文件:

# helloworld_nginx.conf
upstream django {
    server unix:///usr/share/nginx/html/test/helloworld.sock; # for a file socket
    # server 127.0.0.1:5902; # for a web port socket (we'll use this first)
}

# configuration of the server
server {
    # the port your site will be served on
    listen      8024;
    # the domain name it will serve for
    server_name .belter-tuesday.com; # substitute your machine's IP address or FQDN
    charset     utf-8;

    # max upload size
    client_max_body_size 75M;   # adjust to taste

    # Finally, send all non-media requests to the Django server.
    location /morning {
        include     uwsgi_params;
        uwsgi_pass  django;
    }
}

【讨论】:

  • 虽然我认为 0777 过于宽松,您应该找到一种更好的方法来授予正确的用户权限而不是向所有用户开放,但您的解释非常好,帮助我找到了问题所在。
  • 当我运行 uwsgi --socket /tmp/mysite.sock --wsgi-file wsgi.py 它显示!!!没有内部路由支持,用 pcre 支持重建!!! *** 警告:您正在运行没有其主进程管理器的 uWSGI *** 锁定引擎:pthread 强大的互斥锁 Thunder lock:禁用(您可以使用 --thunder-lock 启用它)错误删除 unix 套接字,unlink():操作不允许 [core/socket.c 第 198 行] bind():地址已在使用中 [core/socket.c 第 230 行]
  • 您可以为您的套接字文件更改一个目录而不是/tmp,再试一次。
  • 我的 sock 文件包含 helloworld.sock: No such device or address 并且我的网页没有响应
【解决方案3】:

在 CentOS 上,我尝试了所有这些方法,但仍然无法正常工作。最后,我找到了这篇文章:

https://www.nginx.com/blog/nginx-se-linux-changes-upgrading-rhel-6-6/

对于开发机器,我们只需运行:

semanage permissive -a httpd_t

但是对于一个真正的生产服务器,我还没有弄清楚。 您可能需要尝试上述文章中描述的其他方法。

【讨论】:

  • 这个命令解决了我花了整整一周的时间来解决的问题,谢谢!
  • 谢谢你,解决了我在 CentOS 7 上的问题。我必须用 yum install policycoreutils-python 安装 semanage。
【解决方案4】:

这需要我很多时间才能找到权限问题。 问题当然在于权限。 默认用户是 nginx。 我做了什么: 在/etc/nginx/nginx.conf更改用户:

user  www-data;

接下来将您的用户加入 www-data 组:

usermod -a -G www-data yourusername

接下来设置uwsgi:

[uwsgi]
uid = yourusername
gid = www-data
chmod-socket = 660

然后重启nginx:

sudo systemctl restart nginx

最后重启 uwsgi。

【讨论】:

    【解决方案5】:

    我解决了这个问题一段时间,发现我的uwsgi.ini 文件中的uidgid 标志没有应用于.sock 文件

    您可以通过运行 uwsgi 进行测试,然后使用 linux 命令 ls -l 检查您的 .sock 文件的权限。

    我的解决方案是使用 sudo 运行 uwsgi

    sudo uwsgi --ini mysite_uwsgi.ini
    

    使用包含标志的 .ini 文件:

    chmod-socket = 664
    uid = www-data
    gid = www-data
    

    那么.sock文件的权限是正确的,502 Bad Gateway的错误终于消失了!

    希望这会有所帮助:)

    【讨论】:

      【解决方案6】:

      这个问题让我抓狂。我的环境是centos7+nginx+uwsgi,使用unix socket连接。 接受的答案很棒,只需在其中添加一些点即可。

      ROOT 用户,快速测试

      首先关闭selinux,然后将chmod-socket改为666,最后用root启动uwsgi。

      这样

      setenforce 0 #turn off selinux
      chmod-socket = 666
      uwsgi --ini uwsgi.ini
      

      其他用户

      如果使用自己创建的其他用户启动uwsgi,请确保home文件夹下用户文件夹的权限为755,且属主和组对应。

      例如

      chmod-socket = 666
      usermod -a -G nginx webuser #add webuser to nginx's group
      cd /home/
      chmod -R 755 webuser
      chown -R webuser:webuser webuser
      uwsgi --ini uwsgi.ini --gid webuser --uid webuser
      

      【讨论】:

        【解决方案7】:

        CentOS 用户的另一篇很棒的文章:

        https://axilleas.me/en/blog/2013/selinux-policy-for-nginx-and-gitlab-unix-socket-in-fedora-19/

        虽然关于 CentOS 的答案很有用,但问题在于 SELinux。

        我关注了整篇文章,但我认为以下命令解决了我认为的问题:

        yum install -y policycoreutils-{python,devel}
        grep nginx /var/log/audit/audit.log | audit2allow -M nginx
        semodule -i nginx.pp
        usermod -a -G user nginx
        chmod g+rx /home/user/
        

        请用您的实际用户替换用户以授予权限。同样适用于 chmod 命令下的目录。

        【讨论】:

          【解决方案8】:

          uwsgi.ini

          [uwsgi]
          uid = yourusername
          gid = www-data
          chmod-socket = 664
          

          为什么?因为有时应用程序需要读取或写入文件系统,超出了 Web 服务器可访问的范围。我不想为了适应每一种这样的情况而改变一大堆所有权和权限。我宁愿让我的应用程序像我一样运行并做它需要做的事情。将组设置为 www-data 并将套接字 chmod 为 664 允许该组对其进行写入,从而提供 Web 服务器和应用程序之间唯一必要的通信窗口。

          【讨论】:

            【解决方案9】:

            在开发模式下,如果使用root,只需设置wsgi.ini或emperor.ini如下:

            uid=root
            gid=root
            

            【讨论】:

              【解决方案10】:

              你需要取消注释

              #server 127.0.0.1:8001;
              

              来自上游块,类似地在 uwsgi.ini 中进行更改

              socket = 127.0.0.1:8001
              

              【讨论】:

              • 这将使用互联网套接字类型。 OP 正在尝试使用 unix 套接字进行设置。
              猜你喜欢
              • 2016-05-25
              • 2020-02-08
              • 2017-07-23
              • 2015-04-30
              • 2018-10-02
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多