Gunicorn 无法在 nginx 上创建套接字

Gunicorn 无法在 nginx 上创建套接字

我正在尝试设置 Django、Gunicorn 和 nginx。

我已经配置了 Gunicorn 以便运行,但是似乎在使用 Gunicorn 的 nginx 配置中遇到了问题。

这是我的配置:

/etc/systemd/system/gunicorn.service

[Unit]
Description=gunicorn daemon
Requires=socket
After=network.target

[Service]
PIDFile=/run/gunicorn/pid
User=root
Group=root
RuntimeDirectory=gunicorn
WorkingDirectory=/srv/myproject/current
ExecStart=/srv/venvs/myenv/bin/gunicorn --pid /run/gunicorn/pid   \
          --bind unix:/run/gunicorn/socket myapp.wsgi:application
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target

Gunicorn 状态如下所示

sudo systemctl 状态 gunicorn

gunicorn.service - gunicorn daemon
   Loaded: loaded (/etc/systemd/system/gunicorn.service; enabled; vendor preset: enabled)
   Active: active (running) since Thu 2018-01-18 23:32:11 UTC; 3min 23s ago
  Process: 6347 ExecStop=/bin/kill -s TERM $MAINPID (code=exited, status=0/SUCCESS)
 Main PID: 6355 (gunicorn)
    Tasks: 2
   Memory: 195.7M
      CPU: 1.426s
   CGroup: /system.slice/gunicorn.service
           ├─6355 /srv/venvs/myenv/bin/python3.6 /srv/venvs/myenv/bin/gunicorn --pid /run/gunicorn/pid --bind unix:/run/gunicorn/socket myapp.wsgi:application
           └─6360 /srv/venvs/myenv/bin/python3.6 /srv/venvs/myenv/bin/gunicorn --pid /run/gunicorn/pid --bind unix:/run/gunicorn/socket myapp.wsgi:application

Jan 18 23:32:11 python-server systemd[1]: Stopped gunicorn daemon.
Jan 18 23:32:11 python-server systemd[1]: Started gunicorn daemon.
Jan 18 23:32:11 python-server gunicorn[6355]: [2018-01-18 23:32:11 +0000] [6355] [INFO] Starting gunicorn 19.7.1
Jan 18 23:32:11 python-server gunicorn[6355]: [2018-01-18 23:32:11 +0000] [6355] [INFO] Listening at: unix:/run/gunicorn/socket (6355)
Jan 18 23:32:11 python-server gunicorn[6355]: [2018-01-18 23:32:11 +0000] [6355] [INFO] Using worker: sync
Jan 18 23:32:11 python-server gunicorn[6355]: [2018-01-18 23:32:11 +0000] [6360] [INFO] Booting worker with pid: 6360

我的 nginx 配置

/etc/nginx/sites-enabled/myserver-python

server {
    server_tokens off;
    listen      443 ssl;
    server_name         myserver.com;
    keepalive_timeout   70;

    ssl_certificate     /etc/ssl/certs/myserver.com.merged.crt;
    ssl_certificate_key /etc/ssl/private/myserver.com.key;

    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers         HIGH:!aNULL:!MD5;

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

    location / {
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn/socket;
    }
}

在路径上/run/gunicorn我只能看到pid文件。文件socket从未创建过。

错误日志如下

/var/log/nginx/error.myserver.log

2018/01/18 23:09:00 [crit] 5764#5764: *1 connect() to unix:/run/gunicorn/socket failed (2: No such file or directory) while connecting to upstream, client: 212.251.167.250, server: my-server.com, request: "GET / HTTP/1.1", upstream: "http://unix:/run/gunicorn/socket:/",, host: "myserver.com"

有人能看出这里出了什么问题吗?为什么socket文件没有生成,而pid文件却生成了?

答案1

gunicorn 的套接字实际上如日志条目所示,打开的套接字与 systemd 单元中配置的套接字不同。

日志显示了 gunicorn 实际执行的操作:

Jan 18 23:08:49 python-server gunicorn[5858]: [2018-01-18 23:08:49 +0000] [5858] [INFO] Listening at: unix:/run/gunicorn/socket (5858)

请注意,它实际上打开了/run/gunicorn/socket。但是您的 nginx 配置和 systemd 单元指定打开/run/gunicorn/gunicorn.socket,这是不同的路径。

我的第一个想法是,你可能改变了 systemd 单元中的路径,但还没有运行systemctl daemon-reload。在运行此命令(或重新启动)之前,systemd 单元中的任何更改都不会生效。

因此,我将重新加载 systemd,然后尝试重新启动 gunicorn。

systemctl daemon-reload
systemctl restart gunicorn.service

答案2

配置正确,但问题是 gunicorn 服务没有正确重启。

由于 gunicorn 是作为 systemd 安装的,因此应该使用 重新启动它 systemctl restart gunicorn

之后一切运行正常。

答案3

gunicorn 套接字文件无法创建或不允许读/写访问的另一个原因是 SELinux 阻止访问。SELinux 在 RedHat / Fedora / CentOS 版本的 Linux 中最常见。

例如,如果您正在运行 SELinux,并且守护进程在 /run、/var/run 或其中任何一个下的子目录之外创建套接字文件,则在守护进程重新启动时,套接字文件将具有错误的文件上下文。这将在 SELinux 日志 (/var/log/audit/audit.log) 中显示为如下错误:

type=AVC msg=audit(1569976379.346:40651): avc:  denied  { connectto } for  pid=25861 comm="httpd" path="/home/username/gunicorn.sock" 
scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:system_r:init_t:s0 tclass=unix_stream_socket permissive=0

如果 Web 服务器进程使用的“用户”或“组”权限无权读取/写入套接字文件,则 Web 服务器与套接字通信时也可能会遇到问题。这可能意味着更改 systemd 守护程序的“Unit”文件中的 User=root 或 Group=root(如 OP 中所示)。

systemctl edit --full gunicorn.service

然后重新加载单元文件和 gunicorn

sudo systemctl daemon-reload
sudo systemctl restart gunicorn && systemctl status gunicorn

相关内容