組建Redis叢集遇到`GLIBC_2.14' not found和ps -ef 不顯示使用者名稱

葉金鑫發表於2021-07-09

RHEL6.9組建Redis sentinel叢集遇到兩個問題

今天在元件Redis sentinel 叢集時,遇到兩個問題,之前已經組建多次,都沒碰到類似問題,在解決這兩個問題時,耗費些時間。

問題1. ./redis-server: /lib64/libc.so.6: version `GLIBC_2.14' not found 問題

在將A伺服器 RHEL6.9 上已經編譯好的 Redis-3.0.3 整個目錄,scp 到 RHEL6.9 伺服器B上,

在 A 上能正常執行的redis-server程式,但在 B 伺服器上卻執行失敗,在 B 伺服器redis中的src目錄下使用指令 ldd redis-server 可以看到如下的報錯,

B 伺服器ldd結果:

$ldd redis-server
./redis-server: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by ./redis-server)
        linux-vdso.so.1 =>  (0x00007ffd3fbc7000)
        libm.so.6 => /lib64/libm.so.6 (0x0000003e49a00000)
        libdl.so.2 => /lib64/libdl.so.2 (0x0000003e48a00000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003e49200000)
        libc.so.6 => /lib64/libc.so.6 (0x0000003e48e00000)
        /lib64/ld-linux-x86-64.so.2 (0x0000003e48600000)

但是在 A 伺服器上進行如上的命令,卻正常,並沒有not found。
A 伺服器ldd結果:

$ldd redis-server
        linux-vdso.so.1 (0x00007ffdcdb5b000)
        libm.so.6 => /lib64/libm.so.6 (0x0000003940e00000)
        libdl.so.2 => /lib64/libdl.so.2 (0x0000003940600000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003940200000)
        libc.so.6 => /lib64/libc.so.6 (0x000000393fe00000)
        /lib64/ld-linux-x86-64.so.2 (0x000000393fa00000)

這就奇怪了,但是細心觀察,就能發現 /lib64/libc.so.6 () 的值是不一樣的,初步懷疑是由於在 A 機器上編譯環境和 B 上是不一樣的。

利用相關指令檢視 libc.so.6 中是否一樣:

A 伺服器檢視 libc.so.6 內容:

$ strings /lib64/libc.so.6 |grep GLIBC_  
GLIBC_2.2.5
GLIBC_2.2.6
GLIBC_2.3
GLIBC_2.3.2
GLIBC_2.3.3
GLIBC_2.3.4
GLIBC_2.4
GLIBC_2.5
GLIBC_2.6
GLIBC_2.7
GLIBC_2.8
GLIBC_2.9
GLIBC_2.10
GLIBC_2.11
GLIBC_2.12
GLIBC_2.13
GLIBC_2.14
GLIBC_2.15
GLIBC_2.16
GLIBC_2.17
GLIBC_PRIVATE

B 伺服器檢視 libc.so.6 內容:

$ strings /lib64/libc.so.6 |grep GLIBC_  
GLIBC_2.2.5
GLIBC_2.2.6
GLIBC_2.3
GLIBC_2.3.2
GLIBC_2.3.3
GLIBC_2.3.4
GLIBC_2.4
GLIBC_2.5
GLIBC_2.6
GLIBC_2.7
GLIBC_2.8
GLIBC_2.9
GLIBC_2.10
GLIBC_2.11
GLIBC_2.12
GLIBC_PRIVATE

上述指令對比就能看出,B伺服器的 GLIBC 版本較低,雖然都是RHEL6.9作業系統,但內部庫還是有些不一樣的地方。

對應的解決方法有如下幾種:

  1. 在 B 的環境中,直接進行 redis 原始碼編譯,生成的可執行檔案能在 B 中成功執行。
  2. 可以找到與 B 一樣的 strings /lib64/libc.so.6 |grep GLIBC_ 的作業系統環境,在其上編譯之後,直接將可執行檔案拷貝到B上執行。
  3. 升級 B 伺服器的 GLIBC。
  4. 可在redis原始碼中新增約束,顯式指定所依賴的memcpy函式的GLIBC版本,需新增的約束程式碼如下:
    __asm__(".symver memcpy,memcpy@GLIBC_2.2.5");,【注意】只需在呼叫函式memcpy的原始檔中加入此約束,該方法讀者可以自行驗證,後面參考連結中有相關部落格介紹。

我是選擇了方法2解決的上述報錯問題,找到一個 strings /lib64/libc.so.6 |grep GLIBC_ 和 B 伺服器一樣的內容,重新拷貝redis相關檔案到 B 伺服器中,執行redis程式成功。

問題2. ps -ef 程式 uid 不顯示使用者名稱而是數字

在上述redis於 B 伺服器成功執行後,ps 程式發現第一縱列不是顯示使用者名稱,而是使用者名稱的uid一串數字

$ ps -ef|grep redis
31241    129637 125617  0 17:53 pts/3    00:00:00 ./src/redis-server *:6358   
31241    129866      1  0 17:55 ?        00:00:00 ./src/redis-sentinel *:16358 [sentinel]

在使用linux有一段時間,沒遇到過這種現象,一般顯示都直接是使用者名稱,這樣ps就知道該程式是哪個使用者啟動並有許可權停止的。linux中是嚴格區分使用者,不同非root使用者對不同程式檔案目錄等有不同操作許可權,可以使得多使用者使用同一臺伺服器時的安全。

通過man命令檢視ps命令的說明: 8位使用者名稱的賬戶能夠顯示完整的使用者名稱,9位使用者名稱的賬戶就顯示了UID。
當使用者名稱的長度(使用者名稱字串的字元個數)大於8(預設)時,只會顯示使用者的UID, ps的這個長度可以自定義,如下命令:

ps -o ruser=thereisusername -e -o pid,ppid,c,stime,tty,time,cmd|grep xxx

說明:“thereisusername”是自定義填寫的字串,Linux會自動檢查此字串的長度,使用者名稱長度比該字串小的都會顯示使用者名稱。

在Redis使用和學習中,遇到上述問題,特此總結記錄,加深影響,一點一滴積累Redis和Linux相關知識。

參考連結:

https://blog.csdn.net/Jin_Kwok/article/details/80319441?utm_source=blogxgwz7

https://blog.csdn.net/weixin_34294649/article/details/91699158

本人才疏學淺,如有錯誤不當之處,請批評指正,如有侵權,請立即聯絡我進行刪除。
如果能為您帶來一點點幫助,我將十分高興,也多謝您關注:hongmaolinux 和轉發推薦,謝謝!

image

相關文章