我查看了很多网站,也查看了 ServerFault 中关于这个问题的许多问题/答案。但是,我似乎没有找到配置错误的根源。
我的 nginx 服务器中有 4 个域:
example.com
www.example.com
api.example.com
blog.example.com
nginx.conf
它们都已启动并运行,端口为 80 和 443。这是我为它们所有使用的模板,仅更改了server_name
、root
和指令。还有一些其他更改,但原则上不会产生影响。就像不同的。error_log
access_log
fastcgi_param
example.com
这是和的模板www.example.com
:
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com/public_html/web;
if ($http_host = example.com) {
return 301 https://www.example.com$request_uri;
}
location / {
# try to serve file directly, fallback to front controller
try_files $uri /index.php$is_args$args;
}
location ~ ^/index\.php(/|$) {
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTPS off;
fastcgi_param DATABASE_NAME some_database;
fastcgi_param DATABASE_USER some_user;
fastcgi_param DATABASE_PASSWORD some_pwd;
}
#return 404 for all php files as we do have a front controller
location ~ \.php$ {
return 404;
}
error_log /var/log/nginx/www.example.com_error.log;
access_log /var/log/nginx/www.example.com_access.log;
# Redirect non-https traffic to https
if ($scheme != "https") {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
这是我重新启动服务器时收到的确切错误:
root@vps_server:/etc/nginx# journalctl -xe
Mar 09 09:17:16 vps_server systemd[1]: Starting A high performance web server and a reverse proxy server...
-- Subject: Unit nginx.service has begun start-up
-- Defined-By: systemd
-- Support: http://www.ubuntu.com/support
--
-- Unit nginx.service has begun starting up.
Mar 09 09:17:16 vps_server nginx[30764]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Mar 09 09:17:16 vps_server nginx[30764]: nginx: [emerg] bind() to 0.0.0.0:443 failed (98: Address already in use)
Mar 09 09:17:16 vps_server nginx[30764]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Mar 09 09:17:16 vps_server nginx[30764]: nginx: [emerg] bind() to 0.0.0.0:443 failed (98: Address already in use)
Mar 09 09:17:17 vps_server nginx[30764]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Mar 09 09:17:17 vps_server nginx[30764]: nginx: [emerg] bind() to 0.0.0.0:443 failed (98: Address already in use)
Mar 09 09:17:17 vps_server nginx[30764]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Mar 09 09:17:17 vps_server nginx[30764]: nginx: [emerg] bind() to 0.0.0.0:443 failed (98: Address already in use)
Mar 09 09:17:18 vps_server nginx[30764]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Mar 09 09:17:18 vps_server nginx[30764]: nginx: [emerg] bind() to 0.0.0.0:443 failed (98: Address already in use)
Mar 09 09:17:18 vps_server nginx[30764]: nginx: [emerg] still could not bind()
Mar 09 09:17:18 vps_server systemd[1]: nginx.service: Control process exited, code=exited status=1
Mar 09 09:17:18 vps_server systemd[1]: Failed to start A high performance web server and a reverse proxy server.
-- Subject: Unit nginx.service has failed
-- Defined-By: systemd
-- Support: http://www.ubuntu.com/support
--
-- Unit nginx.service has failed.
--
-- The result is failed.
Mar 09 09:17:18 vps_server systemd[1]: nginx.service: Unit entered failed state.
Mar 09 09:17:18 vps_server systemd[1]: nginx.service: Failed with result 'exit-code'.
当我尝试使用更新证书时,sudo certbot renew --dry-run
我收到了类似的错误,尽管并不完全相同。
如果我关闭 nginx 线程,那么我就可以重新启动服务器。但是下次我尝试重新启动它时,它会抛出相同的错误。最糟糕的是,我无法更新我的 SSL 证书(尽管这可能是由于其他原因,我不想在这里说明,因为这可能是原因)。
编辑
我已经使用 Vagrant 设置了一台本地计算机,配置完全相同,只是我注释了 SSL 证书数据。我可以毫无问题地重新启动服务器。所以也许它确实与 Certbot/SSL 配置有关。
为了帮助调试此问题,这里是输出netstat -tulpn
(只有 nginx 使用端口 80 和 443,据我理解这是预期的输出):
/var/log/nginx# netstat -tulpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN 16700/mysqld
tcp 0 0 0.0.0.0:5355 0.0.0.0:* LISTEN 1578/systemd-resolv
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 30608/nginx: master
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1675/sshd
tcp 0 0 0.0.0.0:25 0.0.0.0:* LISTEN 10001/master
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 30608/nginx: master
tcp6 0 0 :::5355 :::* LISTEN 1578/systemd-resolv
tcp6 0 0 :::22 :::* LISTEN 1675/sshd
tcp6 0 0 :::25 :::* LISTEN 10001/master
udp 0 0 127.0.0.53:53 0.0.0.0:* 1578/systemd-resolv
udp 0 0 0.0.0.0:68 0.0.0.0:* 1343/dhclient
udp 0 0 0.0.0.0:5355 0.0.0.0:* 1578/systemd-resolv
udp6 0 0 :::5355 :::* 1578/systemd-resolv
答案1
你看起来怎么nginx.conf
样?我假设你没有更改配置,可能只是添加了 gzip 和一个新的包含文件夹,以便为网站提供单独的位置。你的每个域/子域都有一个单独的配置文件。例如:
example.com
&www.example.com
api.example.com
blog.example.com
这是因为我假设这些是同一域名下的独立网站。如果它们在同一个网站上,并且只是所谓的子页面,那么您最好只创建带有位置选项的子页面。
为了重新组织您的nginx
配置,我将创建一个com.example.conf
包含 3 个独立服务器部分的文件。首先是将非 www 用户重定向到 www 网站:
server {
listen 80;
server_name example.com;
return 301 https://www.example.com$request_uri;
}
server {
listen 443 ssl;
server_name example.com;
return 301 https://www.example.com$request_uri;
}
第三部分将包含主要站点:
server {
listen 443 ssl;
server_name example.com www.example.com;
root /var/www/example.com/public_html/web;
index index.php;
error_log /var/log/nginx/www.example.com_error.log;
access_log /var/log/nginx/www.example.com_access.log;
location / {
# try to serve file directly, fallback to front controller
try_files $uri /index.php$is_args$args;
}
location ~ ^/index\.php(/|$) {
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTPS off;
fastcgi_param DATABASE_NAME some;
fastcgi_param DATABASE_USER some_user;
fastcgi_param DATABASE_PASSWORD some_pwd;
}
location ~ \.php$ {
return 404;
}
}
(我不得不说,你的 index.php 位置中的 fastcgi 部分对我来说看起来很奇怪,但我会把这个留给你)
然后创建单独的配置文件com.example.api.conf
和com.example.blog.conf
。像以前一样从以前的配置中添加前两个部分,然后您可以为每个子域添加不同的位置配置。
例如我的 laravel 网站有这个:
rewrite ^/index\.php?(.*)$ /$1 permanent;
location / {
try_files $uri @rewrite;
}
location @rewrite {
rewrite ^(.*)$ /index.php/$1 last;
}
location ~ ^/index.php(/|$) {
fastcgi_pass 127.0.0.1:9000;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTPS on;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
fastcgi_read_timeout 299;
}
希望这对您有帮助,如果没有,请评论您的问题。
答案2
修复 bind() 为 0.0.0.0:80 或 443 失败(98:地址已在使用中)的问题
运行以下命令:
sudo pkill -f nginx & wait $!
sudo systemctl start nginx
答案3
我终于解决了这个问题。看来服务器启用了 IPV6,这要求 nginx 配置略有不同。
不要使用这个:
listen 80;
listen 443 ssl;
我必须使用以下内容:
listen [::]:80;
listen [::]:443 ssl;
在这个网站上我得到了更准确、更详细的解释:https://chrisjean.com/fix-nginx-emerg-bind-to-80-failed-98-address-already-in-use/
奇怪的是,我的错误是:
nginx: [emerg] bind() to 0.0.0.0:443 failed (98: Address already in use)
而不是描述的(在我提供的 URL 中):
nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)
但是,这解决了这个问题,我可以毫无问题地重新启动 nginx 服务器。
我设置的 vagrant 服务器没有启用 IPV6,所以这可能与它的行为方式不同有关。