CTC 教育サービス
[IT研修]注目キーワード Python UiPath(RPA) 最新技術動向 Microsoft Azure Docker Kubernetes
さて、第1回、第2回目のコラムではコマンドラインからWEBサーバーの外形監視トラブル原因調査を行う方法をご紹介しました。障害対応は当然のことながら、今目の前でおきている状況に手を突っ込んで解決しなければなりません。今回は、WEBサーバーの内側からトラブルシュートを行う方法について、一例をご紹介したいと思います。本稿中、特にことわりがない場合は、RHELまたはCentOS環境を前提としています。
今回のタイトルが「初見のサーバーを覗いてみよう」なので、障害がおきたサーバーを今から調査しなければならないのか?と引いてしまった方もいると思います。しかし、そもそものWEBサーバーの原理原則を知っていれば、恐れることはありません。特殊な例外を除き、WEBサーバーは次のように動いています。
まず、これが原理原則の一番根幹の部分です。1台のサーバーで複数のWEBサーバープログラムを動かすためなどの理由で、やむを得ず別のポートで待ち受けさせていたりすることもありますが、これは一旦例外としておいておきます。
ブラウザのアドレスバーに入力するURLには、httpやhttpsのポート番号を手入力するケースはほとんどないかと思います。これらのポートはWell-Knownポートといい、インターネット上に公開されるサービスやプロトコルの決まりごとの1つとしてIANA(Internet Assigned Numbers Authority) が管理しています。ですので、特殊なポートでクライアントからの接続を待ち受けているケースを除き、ブラウザに入力するURLにわざわざポート番号を含めなくてよいのです。
いっぽう、WEBサーバーとして動いているホストのほうは、Well-Knownポートに限らず、何らかのポートに着信した接続をどのアプリケーションが受け取り、よしなに処理するかを決めなければなりません。Apacheであれば、httpd.confやssl.confなどのファイルに以下のような記述があれば、Apacheが起動した際にTCP/80やTCP/443ポートで接続を待ち受けるということになります。
設定内容 | 設定箇所 | 備考 |
---|---|---|
Listen 80 | 主に httpd.conf | |
Listen 443 https | 主に ssl.conf | RHELやCentOS等でmod_sslパッケージをインストールした場合、標準でssl.confにSSL/TLSの設定を記述します |
本連載の第2回目で、LinuxホストからcurlコマンドでWEBサーバーのステータスコードを確認する方法について少し触れました。もしステータスコードが取得できていなければ、
という理由が考えられます。動的なプログラムに不具合が生じていたり、静的なファイルであってもアクセス権がないというケースは、そもそもWEBサーバーがエラーを返すケースですので、このケースには当てはまりません。これらの原因をサーバーの内部から特定するには、次の方法で行います。
WEBサーバーそのものがOSごとダウンしているケース
そもそもWEBサーバーにpingも飛ばずネットワークの到達性がないのか、何らかの理由によりOSごとダウンしているのかを切り分けます。物理サーバーであればコンソールから、クラウドやVPSであれば、クラウド事業者が用意しているVNCやシリアルコンソール、APIなどから起動状況を確認し、シャットダウンしているなら起動しましょう。
OSは起動しているが、WEBサーバーの応答がない
一般的にこうしたケースが多いのかと思いますが、一口に「WEBサーバーの応答がない」といっても、必ずしも原因は1つではありません。
まず、先ほど書きましたように、WEBサーバーはTCP/80ポート、TCP/443ポートの接続を待ち受けます。WEBサーバー上では、ssコマンドで確認してみましょう。
$ ss -lnt | egrep '(80|443)' LISTEN 0 128 *:80 *:* LISTEN 0 128 *:443 *:*
コマンドの出力結果で可読性を上げるために、ssコマンドの出力結果から80番ポートと443ポートの行だけをegrepコマンドで抜き出しています。PHP-FPMをTCP/9000番ポートで待ち受けている場合は、これだけでは不十分ですので、9000番ポートもegrepコマンドに引っ掛けてみましょう。
$ ss -lnt | egrep '(80|443|9000)' LISTEN 0 128 127.0.0.1:9000 *:* LISTEN 0 128 *:80 *:* LISTEN 0 128 *:443 *:*
もしここで本来LISTENすべきポートがLISTENしていなければ、そのポートをバインドしているプロセスが起動していないことになります。
それでは、どのプロセスが80番ポート(http)を待ち受けているかをlsofコマンドで確認しましょう。注意点ですが、他のユーザーがバインドしているプロセスを見るためには、sudoコマンドをつけて実行するか、rootユーザーへ昇格してから実行しないといけません。また、「いざログイン その前に」の章でも述べているように、rootユーザーへ昇格またはsudoコマンドの実行は他ユーザーが実行しているプロセスや他ユーザーが権限を持つファイルへの影響を考慮し、慎重に実行する癖をつけましょう。
$ sudo lsof -i:80 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME nginx 6039 root 7u IPv4 12976 0t0 TCP *:http (LISTEN) nginx 6041 nginx 7u IPv4 12976 0t0 TCP *:http (LISTEN) nginx 6042 nginx 7u IPv4 12976 0t0 TCP *:http (LISTEN) nginx 6043 nginx 7u IPv4 12976 0t0 TCP *:http (LISTEN)
このように、80番ポートをバインドしているプロセス(コマンド)はnginxであることがわかりました。
もしnginxコマンドが起動していなければ、上記コマンドで何も表示されませんので、psコマンドでも確認してみます。
$ ps -aef | egrep '([n]ginx|^UID)' UID PID PPID C STIME TTY TIME CMD nginx 6020 6019 0 Oct19 ? 00:00:06 php-fpm: pool www nginx 6021 6019 0 Oct19 ? 00:00:05 php-fpm: pool www nginx 6022 6019 0 Oct19 ? 00:00:06 php-fpm: pool www nginx 6023 6019 0 Oct19 ? 00:00:05 php-fpm: pool www nginx 6024 6019 0 Oct19 ? 00:00:06 php-fpm: pool www nginx 16463 6019 0 Oct19 ? 00:00:04 php-fpm: pool www root 22020 1 0 21:46 ? 00:00:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf nginx 22021 22020 0 21:46 ? 00:00:00 nginx: worker process nginx 22022 22020 0 21:46 ? 00:00:00 nginx: worker process nginx 22023 22020 0 21:46 ? 00:00:00 nginx: worker process
上記の例では、psコマンドの出力を、egrepコマンドによりnginxを含む行か、先頭文字がUIDで始まる行でフィルタリングしています。nginxユーザーが起動しているコマンドはnginxとphp-fpmであることがわかりますので、もし全く応答がなければ、コマンド(デーモン)起動に失敗している可能性がありますので、エラーログを確認しましょう。
WEBサーバーには問題ないが、ファイアウォール(iptablesやアプライアンス型ファイアウォール等)によりアクセスが遮断されている
先ほどの例示のように、WEBサーバープログラムを実行しているホストにおいてssコマンドやpsコマンドでNginxがTCP/80を待ち受けていることが確認でき、外部ホストからWEBサーバーへpingが飛んでいるにもかかわらず、外部ホストからcurlを実行してもステータスコードが返ってこない(000である)場合、
といった理由が考えられます。これらはNginxやApache等のWEBサーバープログラムより下位層のプロトコルで遮断されているためにおきている障害ですので、WEBサーバーからステータスコードを返しようがない、そもそもクライアントからのリクエストをWEBサーバープログラムが受け取っていないという言い方もできます。この場合、WEBサーバープログラム側でやみくもに設定を変更したり再起動をしたりしても意味がなく、ファイアウォールやロードバランサー、あるいはiptablesの調査から着手するべきです。
WEBサーバーホストのiptables設定を確認する場合、rootユーザーで、またはsudoが実行できるユーザーで iptables コマンドか firewall-cmdコマンドで確認しましょう。
本稿のタイトルにも示したように、今回は「初見のサーバー」にログインします。言い換えますと、「普段の姿を知らないはじめて見るサーバー」にログインするということでもあります。お客様にサービスを提供している場合は特に、以下のことを心がけましょう。
今回のコラムで取り上げたコマンドのほとんどは、一般ユーザーで実行可能、つまりrootユーザーへ昇格したりsudoコマンドを実行したりせずに実行できるコマンドばかりです。sudoコマンド実行時にパスワードを求められる際、このような表示を見たことがあるかと思います。
$ sudo lsof -i:443 あなたはシステム管理者から通常の講習を受けたはずです。 これは通常、以下の3点に要約されます:
#1) 他人のプライバシーを尊重すること。 #2) タイプする前に考えること。 #3) 大いなる力には大いなる責任が伴うこと。
[sudo] hamada のパスワード:
出典が不明なので引用することに恐縮してしまうのですが、何かの読み物で「UNIX(のようなマルチユーザーOS)は自分の爪先を拳銃で撃ち抜くような自由があるOSだ」という言説を読んで納得した記憶があります。そして上記に引用したsudoコマンド実行時のメッセージを読むと、自ずとその重要性を理解していただけるはずです。
ここまでの原因特定についておさらいしてみましょう。
• 障害被疑部位はどこか
▸ WEBサーバー自身
√ そもそもOSが起動していない
√ OSは起動しているがWEBサーバープログラムが起動していない
√ WEBサーバープログラムは起動しているが、PHP-FPMなどのWEBアプリケーション・サーバープログラムが起動していない
√ WEBサーバープログラムおよびWEBアプリケーション・サーバープログラムは起動しているが、iptables等の設定不備で外部からの接続を拒否している
√ ネットワークインターフェイスがダウンしている
▸ クライアント<- -> WEBサーバー間のネットワークにおいて、ダウンしているノードがあるか設定に不備がある
√ ルーター
√ スイッチ
√ ロードバランサー
√ ファイアウォール
▸ クライアント
√ そもそもアドレスを間違えて入力していた
√ hostsファイルに違うサーバーのアドレスを記述していた
• WEBサーバー側の原因切り分け方法
▸ ssコマンド
▸ lsofコマンド
▸ psコマンド
▸ iptablesコマンドまたはfirewall-cmdコマンド
いかがでしたでしょうか。初見のWEBサーバーであっても、本稿に示したコマンドと心構えをセットにすることで、勇気をもって立ち向かうことができれば幸いです。次回は、もう少し実践的な内容に踏み込んでみたいと思います。
[IT研修]注目キーワード Python UiPath(RPA) 最新技術動向 Microsoft Azure Docker Kubernetes