首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP file_get_contents() DNS 解析失敗解決方案:VPS /etc/resolv.conf 配置指南

     編輯:PHP 相關知識

file_get_contents() 或 fopen() 讀取遠端 URL 時出現 couldn't resolve host name,本質是 **DNS 解析失敗**。常見於 VPS、Docker 容器、本地開發環境的 `/etc/resolv.conf` 配置缺失或錯誤。本文提供快速修復與永久優化方案。

錯誤現象

Warning: file_get_contents(): couldn't resolve host name in /path/to/script.php on line 10

根因分析

  • PHP 內部網路呼叫依賴系統 DNS 解析器(glibc getaddrinfo)。
  • 容器/VPS 預設 `/etc/resolv.conf` 可能為空、指向不可用 DNS、或被覆蓋。
  • 本地測試正常、部署失敗,通常是開發機有 DNS 快取/Hosts、伺服器無。

快速修復:編輯 /etc/resolv.conf

# SSH 登入 VPS
vi /etc/resolv.conf

# 替換為可靠公開 DNS(推薦順序)
nameserver 114.114.114.114   # 國內電信/聯通/移動優化
nameserver 8.8.8.8           # Google Public DNS
nameserver 1.1.1.1           # Cloudflare DNS
nameserver 223.5.5.5         # 阿里云 DNS

# 保存退出,無需重啟服務,即時生效

驗證指令

# 測試 DNS 解析
dig @114.114.114.114 www.example.com
nslookup www.example.com 8.8.8.8

# PHP 端驗證
php -r 'var_dump(@file_get_contents("https://www.example.com"));'

永久優化方案(防止重啟/網路服務覆蓋)

方案一:systemd-resolved (Ubuntu 18.04+ / Debian 10+)

# 1. 編輯配置
sudo vi /etc/systemd/resolved.conf
[Resolve]
DNS=114.114.114.114 8.8.8.8 1.1.1.1
FallbackDNS=223.5.5.5
Cache=yes

# 2. 重啟並啟用
sudo systemctl restart systemd-resolved
sudo systemctl enable systemd-resolved

# 3. 確保符號連結正確
ls -l /etc/resolv.conf
# 應指向 ../run/systemd/resolve/stub-resolv.conf

方案二:Netplan (Ubuntu 20.04+)

sudo vi /etc/netplan/01-netcfg.yaml
network:
  version: 2
  ethernets:
    eth0:
      dhcp4: true
      nameservers:
        addresses: [114.114.114.114, 8.8.8.8, 1.1.1.1]
        search: [local]
sudo netplan apply

方案三:NetworkManager (CentOS/RHEL/Fedora)

nmcli con mod "System eth0" ipv4.dns "114.114.114.114 8.8.8.8"
nmcli con mod "System eth0" ipv4.ignore-auto-dns yes
nmcli con up "System eth0"

方案四:Docker 容器內固定 DNS

# Dockerfile
RUN echo "nameserver 114.114.114.114\nnameserver 8.8.8.8" > /etc/resolv.conf

# 或 docker run 參數
docker run --dns=114.114.114.114 --dns=8.8.8.8 myimage

# docker-compose.yml
services:
  app:
    dns:
      - 114.114.114.114
      - 8.8.8.8

PHP 程式碼層面防禦性寫法

<?php
function safeFileGetContents(string $url, int $timeout = 10): string|false {
    $ctx = stream_context_create([
        'http' => [
            'timeout' => $timeout,
            'header' => 'User-Agent: PHP/' . PHP_VERSION,
        ],
        'ssl' => [
            'verify_peer' => true,
            'verify_peer_name' => true,
        ]
    ]);
    
    $content = @file_get_contents($url, false, $ctx);
    if ($content === false) {
        $error = error_get_last();
        error_log("file_get_contents failed for $url: " . ($error['message'] ?? 'unknown'));
    }
    return $content;
}

// 重試機制(指數退避)
function fetchWithRetry(string $url, int $maxRetry = 3): string|false {
    for ($i = 0; $i < $maxRetry; $i++) {
        $result = safeFileGetContents($url);
        if ($result !== false) return $result;
        sleep(pow(2, $i)); // 1s, 2s, 4s
    }
    return false;
}
?>

常見誤區提醒

誤區事實
以為是 PHP 代碼錯誤實際是系統網路層 DNS 解析失敗
修改 php.ini 解決php.ini 無 DNS 相關設定
重啟 PHP-FPM 即可DNS 解析由 libc 處理,與 PHP 進程無關
只配置一個 DNS單點故障風險高,建議 2-3 組不同服務商

修正 `/etc/resolv.conf` 或系統級 DNS 配置後,`file_get_contents()`、`cURL`、`SoapClient`、`PDO` 連線等所有網路操作即可恢復正常解析。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved