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 を止めても直らない場合、原因は別の層にあります。確認の順番は次のとおりです。
/etc/nsswitch.confのhosts:の行。filesとdnsの順番や、余計なモジュールが無いか/etc/resolv.confが指すDNSサーバー。dig @そのサーバーで正しい結果が返るか- systemd-resolved を使っている場合は
resolvectl flush-cachesで消してから再確認 - 権威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 自体が不調なら止めても名前解決は動く。ほかのキャッシュと二重なら一本化を検討する