SadServers解説#17 "Cape Town":Borked Nginx
問題概要
シナリオ
故障したNginx
問題詳細
Nginxウェブサーバーがsystemdでインストールされて管理されています。curl -I 127.0.0.1:80
を実行すると、curl: (7) Failed to connect to localhost port 80: Connection refused
と表示されます。デフォルトのNginxページを取得できるように修正してください。
解決判定
Check My Solution
ボタンをクリックしてください。
解答が正解かどうか、コマンドプロンプト上で確認することも可能です。以下と同じ出力が得られた場合は正解です。
$ curl -Is 127.0.0.1:80 | head -1
HTTP/1.1 200 OK
問題解決の方針
【表示する】
今回の問題では、通信が通らない原因を切り分ける力が求められています。
通信が通らない理由として、以下が考えられますね。
- HTTPクライアントが正常に起動していない
- HTTPクライアントは正常に起動しているが、通信が遮断されている
今回は、上のような想定で、原因を切り分けていきましょう。
解決の手順を表示する
- Nginxが問題なく起動しているか確認する
- 起動に問題がある場合は、エラーメッセージに従って対処し、Nginxを再起動します。
- Nginxが起動できるようになっても問題が解決しない場合は、ログを見て対処します。
ヒント
一部、SadServers公式のヒントを改変しています。
ヒント1
まずは、WEBサーバであるNginxが正常に稼働しているか確認します。
実行コマンド
$ systemctl status nginx
● nginx.service - The NGINX HTTP and reverse proxy server
Loaded: loaded (/etc/systemd/system/nginx.service; enabled; vendor preset: enabled)
Active: failed (Result: exit-code) since Wed 2024-05-08 11:45:54 UTC; 49s ago
Process: 576 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=1/FAILURE)
CPU: 31ms
May 08 11:45:54 i-00bccd7ede4ef3a45 systemd[1]: Starting The NGINX HTTP and reverse proxy server...
May 08 11:45:54 i-00bccd7ede4ef3a45 nginx[576]: nginx: [emerg] unexpected ";" in /etc/nginx/sites-enabled/default:1
May 08 11:45:54 i-00bccd7ede4ef3a45 nginx[576]: nginx: configuration file /etc/nginx/nginx.conf test failed
May 08 11:45:54 i-00bccd7ede4ef3a45 systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
May 08 11:45:54 i-00bccd7ede4ef3a45 systemd[1]: nginx.service: Failed with result 'exit-code'.
May 08 11:45:54 i-00bccd7ede4ef3a45 systemd[1]: Failed to start The NGINX HTTP and reverse proxy server.
どうやら、/etc/nginx/sites-enabled/default
というファイルにて、予期しない;
があるようです。要は、設定ファイルの構文エラーですね。
プログラムのデバッグをしたことがある人は、幾度となく目にしたエラーメッセージだと思います…。
ヒント2
/etc/nginx/sites-enabled/default
というファイルにて、予期しない;
があるようなので、ファイルの内容を確認し、構文エラーを修正しましょう。
実行コマンド1
$ sudo less /etc/nginx/sites-enabled/default
;
##
# You should look at the following URL's in order to grasp a solid understanding
# of Nginx configuration files in order to fully unleash the power of Nginx.
…
どうやら、設定ファイルの1行目に、不要な;
が入ってしまっているようです。
念のため、変更を復元できるようにバックアップを取ってから修正しましょう。
実行コマンド2
$ sudo cp /etc/nginx/sites-enabled/default /tmp/default.bak
$ sudo vi /etc/nginx/sites-enabled/default
一行目をコメントアウト
$ sudo diff /etc/nginx/sites-enabled/default /tmp/default.bak
1c1
< # ;
---
> ;
意図通りに設定ファイルを編集できたことが確認出来たら、Nginx
を再起動してみましょう。
ヒント3
設定ファイルを変更したので、Nginxを再起動してみます。
$ sudo systemctl restart nginx
$ systemctl status nginx
● nginx.service - The NGINX HTTP and reverse proxy server
Loaded: loaded (/etc/systemd/system/nginx.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2024-05-08 11:53:41 UTC; 7s ago
Process: 923 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
Process: 924 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
Main PID: 925 (nginx)
Tasks: 2 (limit: 524)
Memory: 2.4M
CPU: 51ms
CGroup: /system.slice/nginx.service
├─925 nginx: master process /usr/sbin/nginx
└─926 nginx: worker process
May 08 11:53:41 i-00bccd7ede4ef3a45 systemd[1]: Starting The NGINX HTTP and reverse proxy server...
May 08 11:53:41 i-00bccd7ede4ef3a45 nginx[923]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
May 08 11:53:41 i-00bccd7ede4ef3a45 nginx[923]: nginx: configuration file /etc/nginx/nginx.conf test is successful
May 08 11:53:41 i-00bccd7ede4ef3a45 systemd[1]: Started The NGINX HTTP and reverse proxy server.
$
$ curl -I 127.0.0.1:80 | head -1
起動はうまくいっているようですが、curl
コマンドを実行したところ、500 Internal Server Error
が発生しているようです。ステータスコード500は、Internal(内部)の名前の通り、サーバ内で問題が発生していることによるエラーです。
起動時にエラーは出ていないようなので、ログファイルを探してログを見てみましょう。
実行コマンド
/var/log/message
やjournalctl
を見てみましたが、参考になるログは出力されていないようです。Nginx
のログを見てみましょう。
$ sudo find /var/log -name nginx
/var/log/nginx
$ ls -la /var/log/nginx
total 234260
drwxr-xr-x 2 root adm 4096 Sep 11 2022 .
drwxr-xr-x 9 root root 4096 May 8 11:45 ..
-rw-r----- 1 www-data adm 239657448 May 8 11:58 access.log
-rw-r----- 1 www-data adm 209425 May 8 11:58 error.log
$ less /var/log/nginx/access.log
$ less /var/log/nginx/error.log
/var/log/nginx/error.log
に気になるエラーが出ていました。
2024/05/08 13:17:15 [alert] 898#898: socketpair() failed while spawning "worker process" (24: Too many open files)
2024/05/08 13:17:15 [emerg] 899#899: eventfd() failed (24: Too many open files)
2024/05/08 13:17:15 [alert] 899#899: socketpair() failed (24: Too many open files)
Too many open filesということで、開いているファイルが多すぎるとのことです。
ヒント4
Nginxのサービスが開くことのできるファイル数の上限を増やしましょう。
Nginxサービスの設定はどこで行われているでしょうか。
実行コマンド
systemdにサービスを登録するためには、管理者用のユニットファイル管理フォルダである/etc/systemd/system
にユニットファイルを配置する必要があります。
ユニットファイルの設定を見てみましょう。
$ cat /etc/systemd/system/nginx.service
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/usr/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
LimitNOFILE=10
[Install]
WantedBy=multi-user.target
LimitNOFILEの値が10になっています。この数字を増やせば良さそうです。
なお、LimitNOFILEとは、Limit Number of File Descriptors(ファイル記述子の数の制限)の略のようです。
実行コマンド
nginx.serviceのLimitNOFILEの値を10から100に変更してみます。
ユニットファイルを変更した際は、systemctl daemon-reload
コマンドで変更を反映することを忘れないようにしましょう。
$ sudo cp /etc/systemd/system/nginx.service /root/nginx.service.bak
$ sudo vi /etc/systemd/system/nginx.service
$ diff /etc/systemd/system/nginx.service /root/ngi
diff: /root/ngi: Permission denied
$ sudo diff /etc/systemd/system/nginx.service /root/nginx.service.bak
14c14
< LimitNOFILE=100
---
> LimitNOFILE=10
$
$ sudo systemctl daemon-reload
$ sudo systemctl restart nginx
$
$ curl -I 127.0.0.1:80 | head -1
HTTP/1.1 200 OK
ユニットファイルの設定値を変更し、再起動することで、無事にNginxがWEBサーバとして動作するようになりました!
ちなみに、systemctl daemon-reload
をしないままsystemctl restart nginx
を実行しようとすると、ちゃんとsystemctl daemon-reload
をしろと怒られます。
$ sudo systemctl restart nginx
Warning: The unit file, source configuration file or drop-ins of nginx.service changed on disk. Run 'systemctl daemon-reload' to reload units.
「いきなり問題を解き始めても調べるばかりになってしまう…」 「やりたいことが分かっても、コマンドが分からない…」 という方は、下記の記事でLinuxのコマンドを復習してから、SadServersの問題に取り掛かってみてはいかがでしょうか。
問題一覧はこちら
Discussion