Nginx错误:连接upstream时出现(13:权限被拒绝)

58

我在我的nginx-error.log文件中遇到了这个错误:

2014/02/17 03:42:20 [crit] 5455#0: *1 connect() to unix:/tmp/uwsgi.sock failed (13: Permission denied) while connecting to upstream, client: xx.xx.x.xxx, server: localhost, request: "GET /users HTTP/1.1", upstream: "uwsgi://unix:/tmp/uwsgi.sock:", host: "EC2.amazonaws.com"

浏览器也显示502 Bad Gateway错误。使用curl命令的输出结果也是一样的,都是Bad Gateway html。

我已经尝试通过将/tmp/uwsgi.sock权限更改为777来修复它,但这没有起作用。我还将自己添加到www-data组中(有几个类似的问题建议这样做)。但是,也不起作用。

这是我的nginx.conf文件:

nginx.conf

worker_processes 1;
worker_rlimit_nofile 8192;

events {
  worker_connections  3000; 
}

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

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;

    sendfile        on; 
    #tcp_nopush     on; 

    keepalive_timeout  65; 

    #gzip  on; 

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

我正在运行一个Flask应用程序,使用Nginsx和Uwsgi,这样可以更加全面地解释。如果有人有任何想法,我会非常感激。


编辑

有人要求我提供我的uwsgi配置文件。所以,我的nginx或uwsgi文件都是由指南here生成的,使用ansible-playbook设置了一切。 nginx.conf文件是自动生成的,但在/etc/uwsgi中除了apps-enabledapps-available文件夹中的README文件之外没有其他内容。我需要为uwsgi创建自己的配置文件吗?我认为ansible会处理所有这些事情。

我相信ansible-playbook已经解决了我的uwsgi配置问题,因为当我运行此命令时

uwsgi -s /tmp/uwsgi.sock -w my_app:app

它启动并输出了这个:

*** Starting uWSGI 2.0.1 (64bit) on [Mon Feb 17 20:03:08 2014] ***
compiled with version: 4.7.3 on 10 February 2014 18:26:16
os: Linux-3.11.0-15-generic #25-Ubuntu SMP Thu Jan 30 17:22:01 UTC 2014
nodename: ip-10-9-xxx-xxx
machine: x86_64
clock source: unix
detected number of CPU cores: 1
current working directory: /home/username/Project
detected binary path: /usr/local/bin/uwsgi
!!! no internal routing support, rebuild with pcre support !!!
*** WARNING: you are running uWSGI without its master process manager ***
your processes number limit is 4548
your memory page size is 4096 bytes
detected max file descriptor number: 1024
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uwsgi socket 0 bound to UNIX address /tmp/uwsgi.sock fd 3
Python version: 2.7.5+ (default, Sep 19 2013, 13:52:09)  [GCC 4.8.1]
*** Python threads support is disabled. You can enable it with --enable-threads ***
Python main interpreter initialized at 0x1f60260
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 72760 bytes (71 KB) for 1 cores
*** Operational MODE: single process ***
WSGI app 0 (mountpoint='') ready in 3 seconds on interpreter 0x1f60260 pid: 26790 (default app)
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI worker 1 (and the only) (pid: 26790, cores: 1)

1
展示uwsgi配置和nginx中的代理。 - iurisilvio
8个回答

60

权限问题是由于uwsgi在每次启动时重置/tmp/uwsgi.sock的所有权和权限为755以及运行uwsgi的用户造成的。

解决问题的正确方法是使uwsgi更改/tmp/uwsgi.sock的所有权和/或权限,以便nginx可以写入此套接字。因此,有三种可能的解决方案。

  1. 将uwsgi作为www-data用户运行,以便该用户拥有其创建的套接字文件。

    uwsgi -s /tmp/uwsgi.sock -w my_app:app --uid www-data --gid www-data
    
  2. 将套接字文件的所有权更改为 www-data 拥有。

  3. uwsgi -s /tmp/uwsgi.sock -w my_app:app --chown-socket=www-data:www-data
    
  4. 更改套接字文件的权限,以便www-data可以写入。

  5. uwsgi -s /tmp/uwsgi.sock -w my_app:app --chmod-socket=666
    

出于不让uwsgi以root用户运行的考虑,我更喜欢第一种方法。

前两个命令需要以root用户身份运行,而第三个命令则不需要。

第一个命令将uwsgi作为www-data用户运行。第二个和第三个命令将uwsgi作为实际运行命令的用户运行。

第一和第二个命令仅允许www-data用户写入socket。而第三个命令允许任何用户写入socket。

出于不让uwsgi以root用户运行并且不让socket文件变成全局可写的考虑,我更喜欢第一种方法。


7
我也遇到了同样的问题,但我使用的是 gunicorn 而不是 uwsgi。该如何解决呢? - Shiva
5
@Shiva,这个问题和答案与gunicorn无关。如果你有关于gunicorn的问题,你应该发布一个单独的问题。 - Susam Pal
1
@Roman,你需要检查为什么uwsgi无法提供适当的访问控制。理论上它应该可以做到,除非你的配置非常特殊。 - silpol
1
@wes 我已经更新了答案,展示了 --uid--gid 选项的用法,这将使uwsgi以非root账户运行。使用这些选项的命令仍然需要以root用户身份运行,但是此命令启动uwsgi以非root用户身份运行。 - Susam Pal
3
在使用--uid--gid选项运行uwsgi之前,您可能需要删除/tmp/uwsgi.sock,因为问题可能是由于您首先以root身份运行uwsgi而没有使用--uid--gid选项。这会导致以root作为所有者创建/tmp/uwsgi.sock文件。后来,当您使用--uid www-data--gid www-data选项运行uwsgi时,www-data无法写入套接字文件,因为此文件的所有者仍然是root。因此,在使用--uid--gid选项之前删除旧的套接字文件将解决该问题。 - Susam Pal
显示剩余7条评论

18

虽然被接受的解决方案正确,但SELinux可能也会阻止访问。如果您已正确设置权限但仍收到“权限被拒绝”的消息,请尝试:

sudo setenforce Permissive

如果它能够运行,那么 SELinux 的问题就显而易见了——或者说是按照预期工作!要为 nginx 添加所需的权限,请执行以下操作:

  # to see what permissions are needed.
sudo grep nginx /var/log/audit/audit.log | audit2allow
  # to create a nginx.pp policy file
sudo grep nginx /var/log/audit/audit.log | audit2allow -M nginx
  # to apply the new policy
sudo semodule -i nginx.pp

之后使用以下命令将SELinux策略重置为强制执行:

sudo setenforce Enforcing

1
谢谢@enaut! selinux确实是我的问题所在。我一直在记录中收到相同的错误消息,一旦我检查了selinux,它就处于强制执行模式。我已经拔了整整一个小时的头发,并双重检查了文件权限,而问题确实是selinux政策。非常感激。 - darekm101
2
很好,但您不需要更改“enforce”模式。有关更多信息,请访问nginx博客:https://www.nginx.com/blog/using-nginx-plus-with-selinux/ - MyounghoonKim
2
这是一个很棒的解决方案。在花费了数小时并重新检查了一切之后,我找到了它。真是太棒了!! - Rakesh Kumar

12

如果您是通过谷歌搜索进入此处,且正在尝试在AWS上使用默认的Ubuntu镜像安装nginx并运行Flask,但仍无法解决问题:

Nginx默认情况下以"user www-data"身份运行,但Digital Ocean最常见的Flask WSGI教程要求您在systemd服务文件中使用登录用户。如果您的Flask/wsgi用户是"ubuntu",则需将Nginx运行的用户从"default"的 "www-data"更改为"ubuntu",您可以通过以下一行脚本完成这个操作:

```bash sed -i 's/user www-data;/user ubuntu;/' /etc/nginx/nginx.conf ```
sudo sed -i 's/user www-data;/user ubuntu;/' /etc/nginx/nginx.conf

尝试让Flask和uwsgi以www-data身份运行并不奏效,但将nginx以ubuntu身份运行就可以很好地工作,因为我在这个实例上运行的只有Flask。

3
这个救了我的命。 - GKV
1
谢谢!在我的Django+Gunicorn+Nginx环境中也起作用了! - Harsha N Hegde
非常感谢,我花了好几个小时才找到这个。 - Andrés Mauricio Gómez

5
Nginx connect to .sock failed (13:Permission denied) - 502 bad gateway

/etc/nginx/nginx.conf 文件的第一行更改用户名称。
默认用户为 www-data,请将其更改为 root 或您的用户名。

它在我的 AWS EC2 Ubuntu 22 上运行成功。 - Philip Rossen

4

我尝试手动更改套接字的权限为666,但仍然出现相同的错误。 - user2497586
@iurisilvio,你能写出语法吗? - Mitul Shah
1
@MitulShah 接受的答案已经有正确的语法了。 - iurisilvio

1

我知道现在可能有些晚了,但这对其他人可能有所帮助。我建议遵循使用virtualenv、uwsgi和nginx运行flask的简单而清晰的文档

如果您在virtualenv中运行项目,则必须激活您的环境。

这是yolo.py文件。

from config import application

if __name__ == "__main__":
    application.run(host='127.0.0.1')

在/tmp/目录中创建uwsgi.sock文件并保留为空。 正如@susanpal的回答所说,“权限问题是因为uwsgi每次启动时都会重置/tmp/uwsgi.sock的所有权和权限为755,并且运行uwsgi的用户”,这是正确的。
因此,每次uwsgi启动时都必须给sock文件授权。 现在按照以下命令操作。
uwsgi -s /tmp/uwsgi.sock -w yolo:application -H /var/www/yolo/env --chmod-socket=666 

和@susanpal的命令稍有不同。对于保持连接,只需在命令末尾添加"&"即可。
uwsgi -s /tmp/uwsgi.sock -w yolo:app -H /var/www/yolo/env --chmod-socket=666 &

1
在我的情况下,更改一些PHP权限就可以解决问题。
sudo chown user:group -R /run/php

我希望这能帮助到某个人。


1
在某些情况下,您应该使用 sudo chown user:group -R /run/php-fpm - SpinyMan

-1
你应该发布您的应用程序的nginx和uwsgi配置文件(位于 /etc/nginx/sites-enabled/ 和 /etc/uwsgi/ 或者任何其他位置)。
通常情况下,请检查您的nginx应用程序配置文件是否有类似以下行的内容:
uwsgi_pass unix:///tmp/uwsgi.sock;

并在您的uwsgi配置文件中使用相同的套接字名称:

socket=/tmp/uwsgi.sock

我没有那个uwsgi配置文件,请参见问题的编辑。即使我能运行uwsgi命令并且它有效,我是否需要一个配置文件? - user2497586
@AlexChumbley 如果您不需要配置文件,则无需创建配置文件。在我看来,配置文件使设置变得更加整洁,因为大多数命令行选项都移动到配置文件中,这意味着您可以在命令中使用更少的选项来进行操作。 - Susam Pal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接