我有一个带有 venvironment 的简单 uwsgi 应用程序。我将项目保存在主文件夹中,sudo user ubuntu。对于测试,我使用了简单的代码:
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return [b"<h1 style='color:blue'>Hello There!</h1>"]
首先,我使用以下命令在测试环境中启动了应用程序:
uwsgi --socket 0.0.0.0:8080 --protocol=http -w main
在实例安全组(在 AWS 上)中,我暂时打开端口 8080 以检查一切是否正常。而且确实有效。
接下来我创建了这个配置:
[uwsgi]
socket = main.sock
chmod-socket = 664
protocol = http
module = main
chdir = /home/ubuntu/operatorAPI
master = true
processes = 5
vacuum = true
die-on-term = true
logto = /home/ubuntu/operatorAPI/log/uwsgi_operator_api.log
然后我创建了服务
/etc/systemd/system/operator_api.service
:
[Unit]
Description=uWSGI instance to serve operator api
After=network.target
[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/operatorAPI
Environment="PATH=/home/ubuntu/operatorAPI/venv/bin"
ExecStart=/home/ubuntu/operatorAPI/venv/bin/uwsgi --ini uwsgi.ini
[Install]
WantedBy=multi-user.target
还为 nginx 创建了一个配置。
server {
listen 80;
server_name uniapi.example.com;
access_log /home/ubuntu/operatorAPI/log/nginx_access.log;
error_log /home/ubuntu/operatorAPI/log/nginx_error.log;
location / {
include uwsgi_params;
uwsgi_pass unix:/home/ubuntu/operatorAPI/main.sock;
}
}
然后我重新启动nginx,启动服务并检查是否登录到域。但没有成功。在 nginx 日志中我读到了这个:
2023/11/22 12:56:03 [crit] 48800#48800: *126 connect() to unix:/home/ubuntu/operatorAPI/main.sock failed (13: Permission denied) while connecting to upstream, client: *****, server: uniapi.example.com, request: "GET / HTTP/1.1", upstream: "uwsgi://unix:/home/ubuntu/operatorAPI/main.sock:", host: "uniapi.example.com"
由于 nginx 日志显示了这一点,这意味着我的域名正确指向我的服务器(我特意用此替换了域名地址,因为我不想在 stackoverflow 上显示它)
我检查了套接字确实是在指定地址创建的。写权限664。
然后,为了测试该服务是否真正工作,我决定更改 uwsgi 设置,而不是设置套接字地址 0.0.0.0:44444。我在 EC2 中打开了一个端口。
[uwsgi]
socket = 0.0.0.0:44444
protocol = http
module = main
chdir = /home/ubuntu/operatorAPI
master = true
processes = 5
vacuum = true
die-on-term = true
logto = /home/ubuntu/operatorAPI/log/uwsgi_operator_api.log
之后我重新启动服务并通过IP和端口登录。一切顺利。
在 nginx 中我替换了这个
uwsgi_pass 0.0.0.0:44444;
但是我仍然无法通过域访问它。仅适用于裸IP和端口。
我也将服务中的用户更改为root,但没有帮助。
附注 最有趣的是,我已经在另一个主机(不是亚马逊)上做了类似的事情,并且一切都在那里工作。也许需要在亚马逊上做一些额外的事情?
在 POSIX 兼容的文件系统中,要打开文件,进程需要对文件路径中的所有目录(从根目录 (
x
) 开始)具有执行权限 (/
)。
在 EC2 使用的 Ubuntu 发行版中,
/home/ubuntu/
是用户 ubuntu
的主目录。默认情况下,像所有主目录一样,它由 ubuntu:ubuntu
所有,并且不向其他目录授予任何权限。
UWCGI进程设置uid为
ubuntu
,因此它可以遍历目录并打开套接字。
Nginx 进程设置为
www-data:www-data
,因此它对 /home/ubuntu
没有执行权限,因此其下没有任何目录或文件。
将 Unix 套接字放在主目录中是一个坏主意。根据文件系统层次结构标准,套接字应位于
/run
或其子目录:
维护瞬态 UNIX 域套接字的系统程序必须将它们放置在此目录或上述适当的子目录中。