Nginx продолжает выдавать ошибку nginx: [emerg] bind() to 0.0.0.0:80 failed (98: адрес уже используется)

Nginx продолжает выдавать ошибку nginx: [emerg] bind() to 0.0.0.0:80 failed (98: адрес уже используется)

Я проверил множество веб-сайтов и много вопросов/ответов здесь, в ServerFault, по этой проблеме. Однако, похоже, я не докопался до сути ошибки конфигурации.

У меня на сервере nginx 4 домена:

  • example.com
  • www.example.com
  • api.example.com
  • blog.example.com

Они все запущены и работают, как в портах 80, так и 443. Это шаблон, nginx.confкоторый я использовал для всех них, изменив только директивы 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 и новую папку include, чтобы иметь отдельное расположение для веб-сайтов. Для каждого вашего домена / поддомена есть отдельный файл конфигурации. Например:

  • 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;
    }
}

(Должен сказать, что часть fastcgi в вашем файле index.php кажется мне странной, но я предоставлю это вам)

Затем создайте отдельные файлы конфигурации как 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, так что это могло быть связано с тем, что он вел себя не так, как раньше.

Связанный контент