Centos 7 的 network 服務 出現 Starting LSB: Bring up/down networking... 錯誤

有時為了測試東西,用虛擬機跑 Windows 以外的作業系統是很平常的事。最近因為想測一下 Jenkins 多節點擴展功能,把很久沒用的 Centos 7 虛擬機,再把它給啟動。

虛擬機雖然是正常啟動了,但是網路卻一直不正常,簡單說就是網卡一直無法啟動連線。

有時基於方便測試,我通常會把 VirtualBox 的網卡,改成橋接模式,讓虛擬機和真實主機都由 IP 分享器配發 IP。這台虛擬機原本的網路架構,是 NAT 架構,雖然有方法可以和真實主機溝通,但會麻煩些。

當我把虛擬機調為橋接模式之後,當然就是要看一下 IP,以方便後續的測試。

ip address show enp0s3

結果我卻沒有看到被配發到任何 IP!

2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:ee:69:28 brd ff:ff:ff:ff:ff:ff

不死心地用 nmcli 再做一下驗證

nmcli device show enp0s3

果然也是 disconnected 的狀態

GENERAL.DEVICE:                         enp0s3
GENERAL.TYPE:                           ethernet
GENERAL.HWADDR:                         08:00:27:EE:69:28
GENERAL.MTU:                            1500
GENERAL.STATE:                          30 (disconnected)
GENERAL.CONNECTION:                     --
GENERAL.CON-PATH:                       --
WIRED-PROPERTIES.CARRIER:               on

再檢查一下網路服務

systemctl status -l network

● network.service - LSB: Bring up/down networking
   Loaded: loaded (/etc/rc.d/init.d/network; bad; vendor preset: disabled)
   Active: failed (Result: exit-code) since Sun 2021-01-24 11:34:54 CST; 3min 32s ago
     Docs: man:systemd-sysv-generator(8)
  Process: 793 ExecStart=/etc/rc.d/init.d/network start (code=exited, status=1/FAILURE)

Jan 24 11:34:53 johncentos systemd[1]: Starting LSB: Bring up/down networking...
Jan 24 11:34:53 johncentos nmcli[840]: gdbusobjectmanagerclient.c:1589: Processing InterfaceRemoved signal for path /org/freedesktop/NetworkManager/DHCP4Config/4 but no object proxy exists
Jan 24 11:34:54 johncentos network[793]: Bringing up loopback interface:  [  OK  ]
Jan 24 11:34:54 johncentos network[793]: Bringing up interface enp0s3:  Error: Connection activation failed: IP configuration could not be reserved (no available address, timeout, etc.)
Jan 24 11:34:54 johncentos network[793]: [FAILED]
Jan 24 11:34:54 johncentos systemd[1]: network.service: control process exited, code=exited status=1
Jan 24 11:34:54 johncentos systemd[1]: Failed to start LSB: Bring up/down networking.
Jan 24 11:34:54 johncentos systemd[1]: Unit network.service entered failed state.
Jan 24 11:34:54 johncentos systemd[1]: network.service failed.

可以很明顯地看到服務啟動失敗。試著把可能的關鍵字,拿去餵 Google,有些說法是因為 ifcfg-*1 設定有誤2,也有些說法是因為和 NetworkManager 這個服務有衝突。

我的設定都是正確的,什麼 MAC,什麼 UUID,都沒有什麼問題,就順手檢查了一下 NetwrokManager 這個服務,它也的確正常啟動。

systemctl status NetworkManager

那我把它停了,總可以啟動 network 服務了吧 XD,結果重啟了 network 服務仍然失敗。

其實我對於 network 會和 NetworkManager 發生衝突,一直抱持著懷疑的看法。原因是這些都是作業系統就有的服務,我也可以肯定我沒有特別調整設定什東西,尤其是網路面的東西。

我特地連入其他雲端的 Centos 主機,查看那兩服務的運作狀況,事實證明是 NetworkManager 可以和平地和 network 共存運作。

不死心地再一次啟動 network 以及 NetworkManager,同時我預期 NetworkManager 會是啟動,但 network 則失敗。結果當然與我預期一致,只是這次我改用 journalctl -xe -u network 來看記錄。

journalctl -xe -u network

其中幾行文字引起了我的注意

Bringing up interface enp0s3:
Determining IP information for enp0s3.../sbin/dhclient: error while loading shared libraries: libdns-export.so.1102: cannot open shared object file: No such file or directory
failed.

大意是說 dhclient 在執行時因為無法載入 libray 檔案,而這也連帶影響我的網路而無法使用。因為 dhclient 是 Linux 向 DHCP 主機取得 IP 的程式,虛擬機我也的確沒有特別指定固定 IP,因為 dhclient 無法啟動向我的 AP 取 IP,也就造成我的網路一直無法使用。

確認 一下有多少個 libray 是 dhclient 需要的3

ldd $(which dhclient) | grep -i found
	libdns-export.so.1102 => not found
	libisc-export.so.169 => not found

缺少了檔案著實令人感到疑惑,就算我再怎麼愛亂搞,也盡可能不去動重要的東西,就算太久沒用這台虛擬機,檔案也不可能就直接自爆。再確認一下缺少的檔案是不是真不存在。

find /usr/lib64 -type f -iname "lib*export.so*"

檔案確實存在,但不是在 /usr/lib64/,反而是在其子目錄 bind9-export 裡,看來我只要把缺少的檔案,從 bind9-export 複製到 /usr/lib64/,或者是在 /usr/lib64/ 建立符號連結 4,就可以解決問題。

我選擇建立符號連結的方式,先執行 dhclient 向 AP 拿 IP,再執行 ip address 也確實看到了由 AP 配發的 IP。把 network 服務啟動,也沒有再出現錯誤。

問題雖然解決了,但一直覺得哪裡怪怪,用 ldd 再比對一下我的虛擬機和雲端主機,看看它們的差異。

# 虛擬機
libdns-export.so.1102 => /lib64/libdns-export.so.1102 (0x00007fdee3384000)
libisc-export.so.169 => /lib64/libisc-export.so.169 (0x00007fdee27ac000)

# 雲端主機
libdns-export.so.1102 => /usr/lib64//bind9-export/libdns-export.so.1102 (0x00007efc5a339000)
libisc-export.so.169 => /usr/lib64//bind9-export/libisc-export.so.169 (0x00007efc59761000)

兩者最大的差別,就是雲端主機的 dhclient 是自動載入 /usr/lib64//bind9-export/ 裡所需要的 lib 檔案,這和我用 find 指令找到的結果一致。換言之,雲端主機的 dhclient 是可以自動去偵測 /usr/lib64/ 下的 bind9-export 子目錄裡 lib 檔,但我的虛擬機卻不會!

這就要從 Kernal 去看了,但簡單來說就是在載入 lib 檔案,是有其一定順序。這個順序如下5

  1. lib 檔內 DT_RPATH 指定的路徑
  2. LD_LIBRARY_PATH 這環境變數所指定的路徑
  3. lib 檔內 DT_RUNPATH 指定的路徑
  4. 讀取 /etc/ld.so.cache 這個快取檔
  5. 32-bit 系統 lib 路徑
    1. /lib
    2. /usr/lib
  6. 64-bit 系統 lib 路徑
    1. /lib64
    2. /usr/lib64

從這順序看下來,就很清楚了,1 和 3 屬於 lib 檔內部的情況,我無法查到 XD,但其他幾個部份,我倒是可以檢查的。而且很快的,就找到問題了。

這個問題是出在快取檔,/etc/ld.so.cache 檔案是存在的,可是它的檔案大小是 0,再對比一下雲端主機的檔案,我幾乎可以肯定問題是出在快取檔。

而這個快取檔的內容,可以透過 ldconfig 這個指令來重建6,而且用法非常簡單,不用特別使用什麼參數

sudo ldconfig

ldconfig 正常會去讀 /etc/ld.so.conf.d/ 裡的設定檔案,如果設定檔是空的,執行 ldconfig 會出現類似如下的錯誤,但這不會造成什麼影響。相反的,則不會有任何訊息提示,要去檢查 ld.so.cache 才知道有沒有重建或更新。

ldconfig: File /lib64/libapr-1.so.0 is empty, not checked.
ldconfig: File /lib64/libapr-1.so.0.4.8 is empty, not checked.
ldconfig: File /lib64/libaprutil-1.so.0 is empty, not checked.
ldconfig: File /lib64/libaprutil-1.so.0.5.2 is empty, not checked.

重建完之後,我們可以用 ldd $(which dhclient) 去檢查其 lib 的相依性,這同時也可以驗證出 lib 的載入順序與我先前所提的順序是一致的的(嗯……應該是 XD)。

因為設定的錯誤,而導致無法連線,這我還算蠻容易遇到。但因為無法載入或缺少相關的 lib 檔,而無法連線算是頭一遭遇到。

參考資料與其他備註

  1. /etc/sysconfig/network-scripts/ []
  2. 通常是 MAC 位址,而且是發生在複製其他虛擬機的情況下 []
  3. https://man7.org/linux/man-pages/man1/ldd.1.html []
  4. symbolic link。有時也會叫它 soft link,軟連結 []
  5. https://man7.org/linux/man-pages/man8/ld.so.8.html []
  6. https://man7.org/linux/man-pages/man8/ldconfig.8.html []

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。

這個網站採用 Google reCAPTCHA 保護機制,這項服務遵循 Google 隱私權政策服務條款