SadServers解説 Medium No.3 「故障したNginx」
問題概要
問題URL
シナリオ
故障した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を再起動し、動作を確認する
- 問題が続く場合はログを確認して対処する
ヒント
オリジナルヒント
ヒント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.
SadServers公式ヒント(翻訳)
ヒント1
Nginxのステータスを確認します: systemctl status nginx
ヒント2
Nginxの設定ファイルを nginx -t で確認します。
ヒント3
/etc/nginx/sites-enabled/default のNginx設定ファイルを修正(先頭の ; を削除)してNginxを再起動した後、再度curlすると500 HTTPエラーが返されます。原因を調べるために /var/log/ ディレクトリのアプリケーションエラーログを確認します。
解法
(前のステップが完了した状態で)スーパーユーザーとして /etc/systemd/system/nginx.service の LimitNOFILE をコメントアウトするか値を増やし、systemctl daemon-reload でsystemdの設定をリロードしてから、systemctl restart nginx でNginxを再起動します。
参考
Nginxの起動トラブルでは、systemctl status nginx で表示されるエラーメッセージが最初の手がかりになります。設定ファイルの構文エラーはよくある原因の一つです。また、systemdのユニットファイルで設定される LimitNOFILE(開けるファイル数の上限)が極端に小さいと、起動はできてもリクエスト処理時にエラーが発生することがあります。
「いきなり問題を解き始めても調べるばかりになってしまう…」 「やりたいことが分かっても、コマンドが分からない…」 という方は、下記の記事でLinuxのコマンドを復習してから、SadServersの問題に取り掛かってみてはいかがでしょうか。
問題一覧はこちら
Discussion