2026年7月27日

2026年7月27日

nscd が原因で名前解決できない場合|古い結果や失敗が残るときの見分け方と直し方

dig では正しいIPが返るのに、curl やPHP、WordPressの外部通信だけが名前解決に失敗する。そんなときは、Linuxの名前解決キャッシュデーモン nscd が古い結果や「失敗した」という結果を覚えている可能性があります。この記事では、nscd が本当に原因かを数分で見分ける方法と、原因として多い順に確認方法と直し方を説明します。設定の細かい値の決め方は別の観点になるため、ここでは「いま名前解決できない」状態から抜け出すことを優先します。

まず症状を整理する

nscd が絡むトラブルには、次のような特徴があります。

  • dig や nslookup では正しい結果が出るが、getent hosts、ping、curl、PHPなどアプリ側では古いIPになる、または解決できない
  • WordPressのサイトヘルスや管理画面で「cURL error 6: Could not resolve host」が出る。プラグインの更新確認や外部APIの呼び出しが失敗する
  • nscd を止めると直る。逆に、DNS側を直しても数分〜数時間は症状が続く
  • サーバーを再起動しても、同じ古い結果が返ることがある

ポイントは、dig と nslookup は nscd を通らないという点です。これらは自前でDNSサーバーに問い合わせるため、OSのキャッシュを見ていません。一方、getent や多くのアプリはglibcの名前解決(NSS)を使い、nscd が動いていればそのキャッシュを先に参照します。この差を使って切り分けます。

nscd が原因かを見分ける

最初に、nscd が動いているか、hostsのキャッシュが有効かを確認します。

systemctl is-active nscd
sudo nscd -g | grep -A3 '^hosts cache'

active と表示され、hosts cache の項目で cache is enabled が yes なら、ホスト名の結果はキャッシュされています。nscd がインストールされていない、または動いていなければ、この記事の原因ではありません。その場合は /etc/resolv.conf や systemd-resolved を疑ってください。

次に、DNSへの直接の問い合わせと、OSの名前解決の結果を並べて比べます。

dig +short www.example.com A
getent ahosts www.example.com

dig が正しく、getent が古い・空になるなら、DNSより手前の層に原因があります。ここで nscd のhostsキャッシュだけを消してから、もう一度 getent を実行します。

sudo nscd -i hosts
getent ahosts www.example.com

これで正しい結果になれば、原因は nscd のキャッシュです。-i hosts はhostsのキャッシュだけを無効にする操作で、ユーザー情報(passwd、group)のキャッシュには影響しません。プロセスを止めないので、本番サーバーでも比較的安全に試せます。消しても変わらない場合は、後半の「nscd 以外の原因」に進んでください。

原因1:一時的な失敗がネガティブキャッシュに残っている

もっとも多いのがこのケースです。DNSサーバーが一瞬応答しなかった、ネットワークが切り替わった、レコードを登録する前に問い合わせてしまった、などで「見つからない」という結果が出ると、nscd はその失敗もキャッシュします。保持時間は /etc/nscd.conf の negative-time-to-live で決まります。

確認は、設定ファイルと実行中の値の両方を見ます。

grep -E '^\s*negative-time-to-live\s+hosts' /etc/nscd.conf
sudo nscd -g | grep -A20 '^hosts cache' | grep 'negative entries'

ここが数分〜数時間など長い値になっていると、一度の失敗が長く尾を引きます。直し方は、まず sudo nscd -i hosts で今の失敗を消し、再発防止として negative-time-to-live hosts を短く(数秒〜数十秒程度)します。変更後は sudo systemctl restart nscd で反映し、nscd -g で実行中の値が変わったことを確かめます。

原因2:DNSを変更したのに古い結果が残っている

サーバー移転や外部サービスのIP変更の直後に起こります。成功した結果は positive-time-to-live の間保持されます。nscd の実装はglibcのバージョンによって差があり、DNSのTTLを考慮せず設定値の間保持していた時期があります。新しめのバージョンではDNSのTTLも考慮されるようになっていますが、手元の挙動は実際に確かめるほうが確かです。

さらに注意したいのが、persistent hosts yes の設定です。これが有効だと、キャッシュはディスク上のファイル(/var/db/nscd/ や /var/cache/nscd/ など、ディストリビューションにより異なります)に保存され、nscd を再起動しても、サーバーを再起動しても読み戻されます。「再起動したのに直らない」の正体は、たいていこれです。

直し方は sudo nscd -i hosts が基本です。再起動で消そうとせず、無効化の操作を使ってください。移転作業が多い環境では、positive-time-to-live hosts をDNS側のTTLと同程度か、それより短い値にしておくと、同じことが起きにくくなります。

原因3:/etc/hosts の変更が反映されていない

移転前の動作確認で /etc/hosts に一時的な行を足したり、消したりしたのに、結果が変わらないケースです。nscd は check-files hosts yes のとき /etc/hosts の更新を検知して、キャッシュを捨てます。この項目が no だと、ファイルを書き換えても古い結果が返り続けます。

grep -E '^\s*check-files\s+hosts' /etc/nscd.conf

no なら yes に変えて再起動します。すぐに直したいだけなら sudo nscd -i hosts でも反映されます。hostsに書いたテスト用の行の消し忘れもよくある原因なので、grep で対象のホスト名が残っていないかも確認してください。

原因4:nscd 自体が不調で、名前解決が遅い・止まる

キャッシュの中身ではなく、nscd のプロセスが応答しなくなっている場合です。アプリは nscd のソケットに問い合わせ、応答を待ってから本来のDNS問い合わせに切り替えるため、「解決はできるが毎回数秒かかる」「PHPのリクエストが詰まってタイムアウトする」という形で現れます。

systemctl status nscd
journalctl -u nscd -n 100 --no-pager
time getent hosts www.example.com

ログにエラーが続いている、プロセスが再起動を繰り返している、getent の応答が明らかに遅い、といった場合は、まず sudo systemctl restart nscd で様子を見ます。それでも改善しなければ、ひとまず sudo systemctl stop nscd で止めると、glibcは nscd を使わずにDNSへ直接問い合わせるようになり、名前解決は通常どおり動きます。止めたうえで原因を調べ、必要がなければ systemctl disable nscd で無効のままにする判断もあります。

原因5:ほかのキャッシュと二重になっている

nscd のほかに systemd-resolved、dnsmasq、SSSD などが動いていると、キャッシュが二段・三段になり、どこに古い値があるのかが分かりにくくなります。

systemctl is-active nscd systemd-resolved sssd dnsmasq

複数が active なら、nscd のhostsキャッシュを止めて一本化することを検討してください。/etc/nscd.conf で enable-cache hosts no にすると、ユーザー情報のキャッシュは残したまま、ホスト名のキャッシュだけを止められます。SSSD を使っている環境では、passwd や group を nscd でもキャッシュすると不整合の原因になるため、SSSD の文書でも nscd 側のキャッシュを無効にするよう案内されています。

nscd 以外の原因

nscd -i hosts でも、nscd を止めても直らない場合、原因は別の層にあります。確認の順番は次のとおりです。

  1. /etc/nsswitch.conf の hosts: の行。files と dns の順番や、余計なモジュールが無いか
  2. /etc/resolv.conf が指すDNSサーバー。dig @そのサーバー で正しい結果が返るか
  3. systemd-resolved を使っている場合は resolvectl flush-caches で消してから再確認
  4. 権威DNSサーバー自体の設定。dig +norec @権威サーバー で正しいか

WordPressのサーバーで確認するときの注意

WordPressの外部通信はPHPのcURLやストリームを使い、名前解決はOSのglibcを通ります。そのため、nscd のキャッシュを消したあと、PHP-FPMを再起動しなくても新しい結果を使うのが普通です。ただし、PHPを含むコンテナで動かしている場合、ホストの nscd はコンテナ内から使われないことが多く、確認する場所はコンテナの中になります。Alpine Linuxなどmuslベースのイメージはそもそも nscd を使わないため、そこで nscd を疑う必要はありません。

設定ファイルを書き換えるときは、事前に sudo cp /etc/nscd.conf /etc/nscd.conf.bak のようにバックアップを取り、可能ならステージング環境で試してから本番に適用してください。nscd の扱いはディストリビューションによって異なり、近年は非推奨扱いにしているものもあります(2026年10月現在)。新しく導入するかどうかは、利用中のディストリビューションの文書を確認してから決めるのが安全です。

まとめ

  • dig は nscd を通らず、getent は通る。この差で nscd が原因かを見分けられる
  • まずは sudo nscd -i hosts でhostsのキャッシュだけを消し、getent で再確認する
  • 多い原因は、一時的な失敗のネガティブキャッシュ、DNS変更後の古い結果、/etc/hosts の変更が検知されない設定
  • persistent hosts yes だと再起動してもキャッシュが残るため、再起動ではなく無効化の操作を使う
  • nscd 自体が不調なら止めても名前解決は動く。ほかのキャッシュと二重なら一本化を検討する

お気軽にご相談ください

お見積りへ お問い合わせへ
▲