Nginx 错误:(13:权限被拒绝)同时连接到上游

Posted

技术标签:

【中文标题】Nginx 错误:(13:权限被拒绝)同时连接到上游【英文标题】:Nginx error: (13: Permission denied) while connecting to upstream 【发布时间】:2014-03-16 05:44:32 【问题描述】:

我的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 Error。 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/*;

我正在运行一个带有 Nginsx 和 Uwsgi 的 Flask 应用程序,只是为了在我的解释中透彻。如果有人有任何想法,我将不胜感激。


编辑

我被要求提供我的 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)

【问题讨论】:

在nginx中显示uwsgi配置和代理。 【参考方案1】:

出现权限问题是因为uwsgi每次启动uwsgi时都会将/tmp/uwsgi.sock的所有权和权限重置为755和运行uwsgi的用户。

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

    以 www-data 用户身份运行 uwsgi,以便该用户拥有它创建的套接字文件。

    uwsgi -s /tmp/uwsgi.sock -w my_app:app --uid www-data --gid www-data
    

    更改套接字文件的所有权,以便 www-data 拥有它。

    uwsgi -s /tmp/uwsgi.sock -w my_app:app --chown-socket=www-data:www-data
    

    改变socket文件的权限,让www-data可以写入。

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

我更喜欢第一种方法,因为它不会让 uwsgi 以 root 身份运行。

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

第一个命令让 uwsgi 以 www-data 用户身份运行。第二个和第三个命令让 uwsgi 以运行该命令的实际用户身份运行。

第一个和第二个命令只允许 www-data 用户写入套接字。第三个命令允许任何用户写入套接字。

我更喜欢第一种方法,因为它不会让 uwsgi 以 root 用户身份运行,也不会使套接字文件成为世界可写的。

【讨论】:

我面临同样的问题,但我使用的是gunicorn 而不是uwsgi。如何解决这个问题..? @Shiva 这个问题和答案与 gunicorn 无关。如果您有关于 gunicorn 的问题,您应该发布一个单独的问题。 @Roman 您必须检查为什么 uwsgi 无法提供适当的访问控制。理论上应该是这样,除非您的配置非常特殊。 @wes 我已经更新了答案以显示--uid--gid 选项的用法,它们会将uwsgi 作为非root 帐户运行。使用这些选项的命令仍需要以 root 用户身份运行,但此命令会启动 uwsgi,使其以非 root 用户身份运行。 @LukeMat 在使用--uid--gid 选项运行uwsgi 之前,您可能需要rm /tmp/uwsgi.sock。出现此问题可能是因为您首先以 root 身份运行 uwsgi 而没有 --uid--gid 选项。这导致 /tmp/uwsgi.sock 文件以 root 作为所有者创建。稍后当您使用--uid www-data--gid www-data 选项运行uwsgi 时,www-data 无法写入套接字文件,因为该文件的所有者仍然是root。因此,在使用 --uid--gid 选项之前删除旧的套接字文件将解决问题。【参考方案2】:

虽然公认的解决方案是正确的,但 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

【讨论】:

感谢@enaut! selinux 确实是我的问题。我在日志中收到了相同的错误消息,一旦我检查了 selinux,它就处于强制模式。在过去的一个小时里,当问题确实出在 selinux 策略上时,我一直在努力检查我的文件权限。非常感谢。 太棒了。但您不需要更改enforce 模式。更多信息请访问 nginx 博客:nginx.com/blog/using-nginx-plus-with-selinux 这是一个很好的解决方案。在花了几个小时重新检查所有内容后,我发现了这一点。简直太棒了!!【参考方案3】:

您必须在 uWSGI 配置中设置这些权限 (chmod/chown)。

它是chmod-socketchown-socket

http://uwsgi-docs.readthedocs.org/en/latest/Options.html#chmod-socket http://uwsgi-docs.readthedocs.org/en/latest/Options.html#chown-socket

【讨论】:

我尝试将套接字上的权限(手动)更改为 666,但它仍然给了我同样的错误。 @iurisilvio 你能写出语法吗? @MitulShah 接受的答案已经具有正确的语法。【参考方案4】:

我知道为时已晚,但它可能对其他人有所帮助。我建议关注Running flask with virtualenv, uwsgi, and nginx 非常简单和甜蜜的文档。

如果您在 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。”它是正确的。

所以你必须在 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 &

【讨论】:

【参考方案5】:

在我的情况下,改变一些 php 权限就可以了

sudo chown user:group -R /run/php

我希望这对某人有所帮助。

【讨论】:

在某些情况下你应该使用sudo chown user:group -R /run/php-fpm【参考方案6】:

任何从 Google 来到这里并尝试在安装 nginx 后使用默认的 Ubuntu 映像在 AWS 上运行 Flask 但仍然无法弄清楚问题所在的人:

Nginx 默认以用户“www-data”运行,但 Digital Ocean 中最常见的 Flask WSGI 教程让您使用登录用户获取 systemd 服务文件。如果您的 Flask/wsgi 用户是“ubuntu”,那么在 /etc/nginx/nginx.conf 中将运行 nginx 的用户从“www-data”(这是默认值)更改为“ubuntu”,一切都将开始工作。您可以在脚本中使用一行来做到这一点:

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

试图让 Flask 和 uwsgi 作为 www-data 运行并没有立即奏效,但是让 nginx 作为 ubuntu 运行工作得很好,因为无论如何我使用这个实例运行的都是 Flask。

【讨论】:

【参考方案7】:

您应该为您的应用程序同时发布 nginx 和 uwsgi 配置文件(在 /etc/nginx/sites-enabled/ 和 /etc/uwsgi/ 中的文件 - 或者您放置它们的任何位置)。

通常检查您的 nginx 应用配置中是否有类似于以下的一行:

uwsgi_pass unix:///tmp/uwsgi.sock;

和你的 uwsgi 配置文件中相同的套接字名称:

socket=/tmp/uwsgi.sock

【讨论】:

我没有那个 uwsgi 配置文件,请参阅问题编辑。即使我能够运行 uwsgi 命令并且它可以工作,我还需要一个吗? @AlexChumbley 如果您不想要配置文件,则无需创建配置文件。在我看来,配置文件使设置更加整洁,因为大多数命令行选项都移到了配置文件中,这意味着您必须在命令中使用更少的选项。

以上是关于Nginx 错误:(13:权限被拒绝)同时连接到上游的主要内容,如果未能解决你的问题,请参考以下文章

Nginx 错误失败(111:连接被拒绝)同时连接到上游,docker-compose nodejs

Apache 权限被拒绝连接到套接字

连接到 Amazon AWS:权限被拒绝

nginx:连接到上游时连接()失败(111:连接被拒绝)

Nginx + Docker Compose-连接到上游时connect()失败(111:连接被拒绝)

403 nginx 错误 - 权限被拒绝