Binary Linux không chạy: glibc hay musl?
Lỗi “GLIBC_2.34 not found” là do máy build đặt glibc tối thiểu. Xem binary thực sự cần gì và chọn 1 trong 4 cách ship portable.
Vì sao một binary Linux không chạy trên server cũ
Khó tạo một binary Linux portable vì glibc, thư viện GNU C, chỉ đảm bảo khả năng tương thích theo một chiều. Binary cũ vẫn chạy trên glibc mới. Binary mới không chạy trên glibc cũ. Máy bạn dùng để compile sẽ đặt ra phiên bản nền thấp nhất cho mọi máy được deploy.
Thông báo lỗi nêu chính xác phiên bản mà binary yêu cầu:
./mytool: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.38' not found (required by ./mytool)Không có gì bị hỏng và thường cũng không có gì được cấu hình sai. Ngoại lệ duy nhất là thiết lập LD_LIBRARY_PATH điều hướng loader đến một libc cũ hơn; đường dẫn trong thông báo cho biết binary thực sự đã đọc libc nào. Dynamic loader đọc version tag được ghi bên trong binary, tìm tag đó trong libc, không tìm thấy và từ chối khởi động chương trình. Tải lại file và chạy chmod +x không thay đổi gì, vì yêu cầu này được ghi trực tiếp trong file. Bạn phải thay đổi cách build binary hoặc thay đổi thứ được ship.
glibc symbol versioning thực sự làm gì
Mỗi function mà glibc export đều có một version tag. printf bên trong libc.so.6 thực chất là printf@@GLIBC_2.2.5. Khi glibc thay đổi behavior hoặc ABI (application binary interface) của một function, nó không thay thế function cũ. Nó giữ code cũ dưới tag cũ và thêm code mới dưới tag mới, nên một libc.so.6 có thể chứa nhiều version của cùng một symbol cùng lúc. Một binary từ năm 2009 vẫn tìm thấy tag của năm 2009, nên forward compatibility hoạt động rất tốt.
Bước link ghi lại những gì nó đã sử dụng. Binary của bạn có một section .gnu.version_r, về bản chất ghi rằng: "Tôi cần GLIBC_2.38 từ libc.so.6". libc cũ hơn chưa từng có tag đó, nên loader dừng trước khi main chạy. Không có fallback, vì fallback sẽ khiến chương trình âm thầm nhận một function khác với function mà nó được compile dựa trên.
Trigger phổ biến nhất từ năm 2021 là glibc 2.34. Bản release đó gộp libpthread và libdl vào libc, đồng thời chuyển __libc_start_main, function khởi động mọi chương trình C, sang tag GLIBC_2.34. Vì vậy, một chương trình hello-world được compile trên bất kỳ distribution nào có glibc 2.34 hoặc mới hơn sẽ yêu cầu GLIBC_2.34, dù source không gọi bất kỳ thứ gì hiện đại. Đây là lý do vấn đề xuất hiện đột ngột với những người có code riêng không thay đổi trong nhiều năm.
Phiên bản glibc nào được distro của tôi phát hành?
Dữ liệu đằng sau biểu đồ này
[
{
"distro": "CentOS 7",
"glibc": 2.17
},
{
"distro": "RHEL 8",
"glibc": 2.28
},
{
"distro": "Ubuntu 20.04",
"glibc": 2.31
},
{
"distro": "Debian 11",
"glibc": 2.31
},
{
"distro": "RHEL 9",
"glibc": 2.34
},
{
"distro": "Ubuntu 22.04",
"glibc": 2.35
},
{
"distro": "Debian 12",
"glibc": 2.36
},
{
"distro": "Ubuntu 24.04",
"glibc": 2.39
},
{
"distro": "Debian 13",
"glibc": 2.41
}
]Đó là các phiên bản mà từng distribution phát hành trong repository riêng, theo thông tin do các distribution công bố và còn hiệu lực vào tháng 8 năm 2026. CentOS 7 đã hết vòng đời từ lâu, nhưng vẫn có trong danh sách vì các server kế thừa vẫn còn chạy nó. Trên bất kỳ máy nào bạn quản trị, hãy kiểm tra bằng ldd --version; lệnh này in bản release của glibc ở dòng đầu tiên. Bạn cũng có thể dùng getconf GNU_LIBC_VERSION.
Hãy đọc 9 dòng đó như một bậc thang. Build trên Debian 13 với glibc 2.41 thì kết quả sẽ không chạy được trên phiên bản nào cũ hơn Debian 13. Build trên Ubuntu 20.04 với glibc 2.31 thì cùng source đó chạy được trên mọi dòng nằm phía trên, bao gồm cả máy Debian 13. Server cũ nhất mà bạn phải hỗ trợ là build host duy nhất cần quan tâm. Vì vậy, distribution bạn chuẩn hóa sẽ xác định ABI floor cho mọi thứ bạn compile cho hệ thống đó. Bạn nên quyết định việc này trước khi fleet hình thành, cùng với các trade-off khác khi chọn OS để chạy trên VPS.
Cách tìm phiên bản glibc tối thiểu mà một binary yêu cầu
Đọc thông tin đó trực tiếp từ file. Cách này áp dụng được cho mọi binary, kể cả binary do vendor cung cấp mà không có ghi chú build.
objdump -T ./mytool | grep -o 'GLIBC_[0-9.]*' | sort -Vu | tail -5Dòng cuối cùng là phiên bản tối thiểu. Nếu thiếu objdump, hãy cài package binutils. Nếu không thể cài thêm gì trên máy đó, strings -a ./mytool | grep -o 'GLIBC_[0-9.]*' | sort -Vu | tail -5 vẫn cho kết quả gần đúng, vì các tag được lưu dưới dạng chuỗi thuần văn bản bên trong file.
readelf -V ./mytool hiển thị cùng yêu cầu đó theo dạng có cấu trúc. Tìm block có tiêu đề Version needs section '.gnu.version_r'. Block này liệt kê một dòng Name: GLIBC_x.y cho mỗi tag, được nhóm theo library phải cung cấp tag đó.
Để biết function nào xác định phiên bản tối thiểu, hãy grep tag đó: objdump -T ./mytool | grep GLIBC_2.38. Tag này thường chỉ tương ứng với một symbol, và đôi khi là symbol bạn có thể tránh dùng. Nếu objdump -T không in ra gì, binary được link tĩnh, nên không có dynamic symbol table và không có yêu cầu về version để in ra.
file và readelf -d cho biết gì về một binary do người khác cung cấp
file cho biết architecture và link type trên cùng một dòng.
file ./mytoolMột bản build glibc thông thường sẽ hiển thị như sau:
ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=..., for GNU/Linux 3.2.0, not strippedBản build static hiển thị statically linked và không có interpreter. Bản build musl hiển thị một interpreter khác:
ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-x86_64.so.1, ...Interpreter là trường quan trọng nhất. Đây là dynamic loader mà kernel chạy trước chương trình của bạn, và path chính xác đó phải tồn tại trên máy đích. /lib/ld-musl-x86_64.so.1 không có sẵn trên server Debian hoặc Ubuntu, trừ khi có người đã cài musl trên đó.
readelf -d ./mytool liệt kê các shared library mà binary yêu cầu theo tên:
Dynamic section at offset 0x2d58 contains 27 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libssl.so.3]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000001d (RUNPATH) Library runpath: [$ORIGIN/../lib]Mỗi mục NEEDED là một yêu cầu bắt buộc và được đối chiếu bằng soname. libssl.so.3 là OpenSSL 3, vì vậy binary đó sẽ không load trên server chỉ có libssl.so.1.1. Soname là nguyên nhân: soname khác nhau có nghĩa là ABI không tương thích một cách có chủ đích. RUNPATH thêm các thư mục để loader tìm các dependency trực tiếp của binary, sau mọi thiết lập LD_LIBRARY_PATH nhưng trước system library cache và các path mặc định. $ORIGIN mở rộng thành thư mục chứa binary. Đây là cách một bundle tự chứa tìm thấy library của chính nó.
Không chạy ldd trên binary mà bạn không tin cậy. Trên glibc, ldd có thể resolve dependency bằng cách chạy chương trình dưới loader, nên file độc hại có thể thực thi code. readelf và objdump chỉ đọc các byte. Trước tất cả các bước này, hãy xác nhận download là file mà project thực sự đã publish, vì xác minh download bằng checksum đã được publish là bước duy nhất cho biết các byte bạn đang giữ thuộc về ai.
Các lỗi bạn thực sự sẽ thấy và ý nghĩa của từng lỗi
Loader báo một phiên bản GLIBC mà nó không tìm thấy. Binary được compile dựa trên glibc mới hơn phiên bản có trên target. Không có thành phần nào cài thêm trên target có thể sửa lỗi này một cách an toàn. Chọn một trong 4 tùy chọn dưới đây.
Shell báo No such file or directory với một file mà bạn vẫn nhìn thấy rõ. Thành phần bị thiếu là interpreter, không phải binary. execve trả về ENOENT khi loader path trong ELF header không tồn tại, và shell chỉ có thể in ra thông báo đó. Chạy file rồi đọc interpreter path. Binary được link với musl trên server chỉ có glibc sẽ gây đúng triệu chứng này.
cannot execute binary file: Exec format error thường có nghĩa là sai architecture: binary x86-64 chạy trên server arm64 hoặc ngược lại. Lỗi này cũng có thể xảy ra khi file hoàn toàn không phải executable hợp lệ, chẳng hạn download bị cắt ngắn hoặc hỏng. Dòng đầu tiên trong output của file cho biết architecture của file hoặc cho biết file không phải là ELF executable có thể sử dụng.
error while loading shared libraries: libssl.so.3: cannot open shared object file có nghĩa là thiếu thư viện NEEDED hoặc thư viện đang tồn tại dưới một soname khác. Cài distribution package tương ứng. Tên package khác nhau giữa các họ distribution, vì vậy hãy chuyển đổi trước khi copy một dòng apt từ README. Các lệnh tương đương giữa dnf và apt bao quát việc chuyển đổi này.
Một Segmentation fault đơn độc từ bản build bằng musl nhưng vẫn chạy tốt dưới glibc. Thường nguyên nhân là thread stack size, được đề cập trong tùy chọn 2.
Bốn cách phát hành binary Linux portable
Mỗi lựa chọn đều có chi phí thực tế. Hãy chọn dựa trên cách chương trình hoạt động khi chạy, không phải dựa trên lựa chọn nghe có vẻ gọn nhất.
Lựa chọn 1: build trên bản distro cũ nhất mà bạn hỗ trợ
Đây là câu trả lời ít hấp dẫn nhất và thường là câu trả lời đúng. Hãy compile trong container image của bản phân phối cũ nhất mà bạn cam kết hỗ trợ. Linker chỉ có thể ghi các tag mà glibc cũ đó thực sự có, vì vậy mức tối thiểu sẽ là bản release đó, trong khi binary vẫn là dynamic binary thông thường và giữ nguyên toàn bộ hành vi của glibc.
docker run --rm -v "$PWD:/src" -w /src ubuntu:20.04 sh -c 'apt-get update && apt-get install -y build-essential && make'Output sẽ chạy trên glibc 2.31 và mọi phiên bản cao hơn. Đừng chỉ giả định; hãy xác minh. Chạy one-liner objdump -T ở phần trước trên kết quả và kiểm tra xem tag cao nhất có đúng với giá trị bạn mong đợi không.
Cái giá phải trả là toolchain. Base image cũ cũng đi kèm compiler cũ, gây vấn đề khi code của bạn cần chuẩn C++ mới. Go và Rust phần lớn tránh được vấn đề này vì toolchain của chúng được cài độc lập vào container, không phụ thuộc vào các package của distro. Với C và C++, bạn có thể thêm compiler mới hơn từ toolchain channel của chính distro, hoặc dùng các image manylinux, vốn được tạo ra chính để kết hợp glibc rất cũ với GCC hiện tại. C compiler đi kèm của Zig cũng có thể target trực tiếp một glibc được chọn, như trong zig cc -target x86_64-linux-gnu.2.28. Cách này cho cùng mức tối thiểu mà không cần duy trì một image cũ.
Tùy chọn 2: liên kết tĩnh với musl
musl là một thư viện C nhỏ được thiết kế cho liên kết tĩnh. Binary musl tĩnh chứa sẵn libc của nó, không khai báo interpreter và chạy trên mọi Linux kernel đúng kiến trúc. Đây là cách phần lớn các bản tải xuống của tool một file được build.
sudo apt install -y musl-tools
musl-gcc -static -O2 hello.c -o hello
file ./hellofile giờ phải hiển thị statically linked, không có trường interpreter. Với Rust, thêm target rồi build cho target đó:
rustup target add x86_64-unknown-linux-musl
cargo build --release --target x86_64-unknown-linux-muslGo không cần các bước này. Với CGO_ENABLED=0 go build, kết quả vốn đã là static và hoàn toàn không liên kết với libc.
Tra cứu NSS thay đổi. glibc phân giải user và hostname thông qua NSS (name service switch), cơ chế này load các module libnss_* bằng dlopen trong khi chương trình đang chạy. glibc được liên kết tĩnh không làm được việc đó, và linker sẽ cảnh báo bằng đúng các dòng sau:
warning: Using 'getaddrinfo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linkingmusl tránh cảnh báo này vì không triển khai NSS. Nó có resolver riêng và đọc trực tiếp /etc/resolv.conf và /etc/hosts. Trên một VPS thông thường, cách này đủ dùng và đơn giản hơn. Trên host lấy account hoặc hostname từ LDAP hay SSSD, binary của bạn sẽ không thấy chúng, trong khi mọi chương trình khác trên máy vẫn thấy. Resolver của musl cũng mới hơn glibc: cơ chế fallback sang TCP cho DNS response quá lớn đối với UDP được thêm vào musl 1.2.4 trong năm 2023. Binary build với musl cũ hơn không thể query các DNS record lớn, và việc lookup có thể fail khi recursive nameserver trả về UDP reply bị truncate nhưng không có partial result.
dlopen không hoạt động. Trong binary musl tĩnh, dlopen chỉ là stub và luôn fail. Mọi thứ load code lúc runtime đều không dùng được: plugin system, PAM module, GPU driver và các module character-set iconv của chính glibc. Nếu chương trình cần dlopen, bạn không thể dùng liên kết tĩnh và phải chọn một trong 3 cách còn lại.
Bạn phải tự quản lý security update. Binary liên kết động nhận được bản sửa lỗi libc ngay khi server chạy package upgrade. Binary tĩnh thì không bao giờ tự nhận. Khi một mục CVE (common vulnerabilities and exposures) xuất hiện đối với libc của bạn hoặc đối với OpenSSL tĩnh được bundle kèm, bạn phải rebuild và phân phối lại. Mọi bản đã deploy vẫn dễ bị tấn công cho đến khi có người thay thế file. Hãy ghi lại những gì đã được liên kết vào binary, vì không có thông tin nào trên target cho administrator biết binary một file của bạn chứa library từ 2 năm trước.
License thay đổi. glibc dùng LGPL, và liên kết tĩnh kích hoạt nghĩa vụ relink của LGPL: bạn phải cung cấp cho người nhận những thứ họ cần để relink chương trình với một glibc khác. musl dùng MIT và không có điều kiện như vậy. Đây là lý do chính khiến các project phân phối binary một file chọn musl thay vì glibc tĩnh.
2 khác biệt runtime có thể gây crash khó hiểu. Thread stack mặc định của musl là 128 KiB. glibc lấy giá trị mặc định từ stack limit lúc chương trình khởi động. Giá trị này thường nằm trong khoảng 2 đến 10 MB. Trên hầu hết kiến trúc, glibc dùng 2 MB nếu limit đó là unlimited. Vì vậy, code đặt buffer lớn trên thread stack có thể gây segfault dưới musl mà không có message hay log line nào. Đặt kích thước rõ ràng bằng pthread_attr_setstacksize hoặc chuyển buffer sang heap. Allocator của musl cũng được thiết kế cho kích thước nhỏ và hành vi có thể dự đoán, thay vì phục vụ nhiều thread cùng cấp phát. Vì vậy, các chương trình nhiều thread và cấp phát nhiều có thể chạy chậm hơn đáng kể. Hãy benchmark workload thực tế của bạn thay vì dựa vào danh tiếng của một trong hai library.
Tùy chọn 3: đóng gói loader và các thư viện
Đặt các thư viện cạnh binary cùng với loader tương ứng, rồi khởi động chương trình thông qua loader đó.
./ld-linux-x86-64.so.2 --library-path ./lib ./mytoolĐể áp dụng vĩnh viễn, ghi các đường dẫn vào file bằng patchelf:
patchelf --set-interpreter "$PWD/lib/ld-linux-x86-64.so.2" --set-rpath '$ORIGIN/lib' ./mytoolMột quy tắc quyết định cách này có hoạt động hay không: loader và libc.so.6 phải đến từ cùng một bản build glibc. Đây là một cặp tương ứng. Việc trộn loader của host với libc được đóng gói sẽ làm chương trình crash khi khởi động thay vì hiển thị lỗi dễ đọc. Hoặc đóng gói cả hai, hoặc không đóng gói cái nào.
AppImage là một dạng đóng gói của mô hình này. Payload nằm trong squashfs image và một runtime nhỏ sẽ mount image đó. Có một điểm thường bị bỏ qua: hầu hết AppImage để host cung cấp glibc thay vì đóng gói glibc. Vì vậy, một AppImage được build theo cách này trên distribution hiện tại vẫn gặp cùng lỗi version khi chạy trên server cũ. Hướng dẫn best practice của AppImage yêu cầu build trên base không mới hơn system cũ nhất mà bạn hỗ trợ. Do đó, AppImage kiểu này chỉ là format phân phối xây trên tùy chọn 1, không phải giải pháp thay thế tùy chọn đó. Bạn cũng có thể đóng gói glibc: appimage-builder và go-appimage đều có thể ship glibc bên trong AppImage. AppImage được build theo cách này có thể chạy trên các distribution cũ hơn và mới hơn system dùng để build. Đổi lại, file sẽ lớn hơn và các thư viện như libssl sẽ bị cố định trong bundle.
Trên headless server, AppImage cần FUSE (filesystem in userspace) để mount payload. Image VPS tối giản thường không có FUSE. AppImage được build với runtime cũ cần thư viện FUSE 2 trên host. Trên Debian và Ubuntu, thư viện này được đóng gói dưới tên libfuse2; trên Ubuntu 24.04, tên này đổi thành libfuse2t64. Khi thiếu thư viện, AppImage dừng với AppImages require FUSE to run.. AppImage mới hơn có sẵn hỗ trợ FUSE 3 và không còn cần cài libfuse trên host. Bạn có thể bỏ qua bước mount bằng ./App.AppImage --appimage-extract-and-run. Tùy chọn này giải nén vào một thư mục tạm rồi thực thi từ đó.
Tùy chọn 4: phát hành container image
Đưa toàn bộ userland đi cùng chương trình. Image có sẵn libc riêng, nên glibc của host không còn quan trọng; chỉ kernel và architecture cần tương thích. Đây là tùy chọn ít phức tạp nhất và loại bỏ hoàn toàn nhóm vấn đề này. Vì vậy, rất nhiều server software được phân phối theo cách này. Chạy Docker trên VPS là cách thông thường để sử dụng image.
Kernel của host vẫn đặt ra giới hạn. glibc mới hơn sử dụng các system call mới hơn, và một container host cũ có thể chặn chúng: glibc 2.34 trở lên sử dụng clone3, nhưng các seccomp profile mặc định cũ sẽ từ chối system call này. Triệu chứng là chương trình fail ngay lập tức với Operation not permitted mà không có thông báo nào nhắc đến glibc. Nâng cấp container runtime trên host sẽ khắc phục lỗi, vì việc chặn nằm trong syscall filter của runtime, không phải trong kernel.
Các chi phí là những yêu cầu thông thường. Máy đích cần có container runtime và quyền sử dụng runtime đó. Dung lượng tải xuống tăng từ một file lên hàng chục hoặc hàng trăm megabyte. Bạn phải quản lý base image và lịch patch của image, nên công việc bảo mật từng tránh được ở tùy chọn 2 quay trở lại dưới dạng rebuild image. Với một service chạy lâu dài, đây là sự đánh đổi hợp lý. Với một command-line tool chỉ được chạy một lần, thì không.
Bạn nên chọn phương án nào?
- Công cụ nội bộ dành cho các server bạn kiểm soát và đều chạy cùng một distribution: build động trên distribution đó rồi dừng ở đó.
- Một file duy nhất để người lạ tải xuống và chạy: dùng static musl nếu chương trình không cần
dlopenvà không cần các tra cứu được NSS hỗ trợ. - Chương trình có plugin hoặc cần GPU: tiếp tục dùng build động, build trên một base cũ và dùng phương án 3 để phân phối.
- Service chạy lâu dài trên máy đã có sẵn runtime: phân phối image.
Dù chọn phương án nào, hãy ghi lại và kiểm tra. glibc trên build host giờ là một phần của quy trình release. Một build machine được nâng cấp từ bản LTS này lên bản LTS tiếp theo sẽ âm thầm nâng mức yêu cầu tối thiểu, khiến những người dùng vẫn chạy được vào tháng trước bị lỗi. Pin build image bằng tag và kiểm tra tag GLIBC_ cao nhất trong output như một build step. Khi đó, bước kiểm tra sẽ fail trong pipeline của bạn thay vì fail trên terminal của người khác.
FAQ
Vì sao tôi nhận được lỗi "version GLIBC_2.38 not found" trên server?
Binary được compile trên một máy có glibc mới hơn glibc trên server của bạn. Symbol versioning của glibc chỉ cung cấp khả năng tương thích tiến: binary cũ chạy được trên glibc mới, nhưng binary mới không chạy được trên glibc cũ, vì loader cần đúng version tag được ghi trong file còn libc cũ không bao giờ có tag đó. Không có cách cài thêm thành phần nào trên server để sửa lỗi này một cách an toàn. Hãy rebuild trên base image cũ hơn, ship bản build static dùng musl, bundle các library cùng loader tương ứng, hoặc ship container image.
Làm thế nào để biết binary cần phiên bản glibc nào?
Đọc các version tag trong file bằng objdump -T ./mytool | grep -o 'GLIBC_[0-9.]*' | sort -Vu | tail -5. Dòng cuối là phiên bản glibc thấp nhất có thể load binary đó. readelf -V ./mytool hiển thị cùng các yêu cầu trong section .gnu.version_r, được nhóm theo library cần cung cấp chúng. Nếu objdump -T không in gì, binary là static và hoàn toàn không yêu cầu glibc. So sánh kết quả với phiên bản trên chính server, lấy bằng ldd --version.
Binary dùng musl có chậm hơn binary dùng glibc không?
Điều này phụ thuộc workload, và cách trả lời chính xác là đo thực tế. Binary static dùng musl khởi động nhanh hơn vì không cần chạy loader và không cần thực hiện relocation khi exec. Ngược lại, allocator của musl được thiết kế để có kích thước nhỏ và hành vi dễ dự đoán, thay vì phục vụ nhiều thread cùng allocate tại một thời điểm. musl cũng có ít routine xử lý string và memory được tối ưu thủ công hơn glibc, nên các chương trình nhiều thread và có workload allocate hoặc xử lý string nặng có thể chậm hơn rõ rệt. Hãy benchmark chính chương trình của bạn trên chính server của bạn trước khi chấp nhận bất kỳ nhận định nào.
Vì sao bash báo "No such file or directory" cho một file đang tồn tại?
File bị thiếu là dynamic loader, không phải binary của bạn. Kernel đọc interpreter path từ ELF header và trả về ENOENT khi path đó không tồn tại, còn shell chỉ có thể hiển thị lỗi bằng thông báo duy nhất mà nó nhận được. Chạy file ./mytool và đọc field interpreter. Nếu kết quả là /lib/ld-musl-x86_64.so.1 trên server Debian hoặc Ubuntu, bạn đang chạy binary được link với musl trên hệ thống glibc. Hãy cài musl runtime của distribution, tức package musl trên Debian và Ubuntu, hoặc lấy bản build dùng glibc hay bản build static của chương trình.
Tôi có thể copy libc.so.6 từ server mới hơn để sửa lỗi này không?
Không. libc.so.6 và ld-linux-x86-64.so.2 là một cặp khớp nhau từ cùng một glibc build. Mọi chương trình glibc được link động trên máy đều dùng chúng, nên ghi đè bản system có thể khiến server không chạy được gần như bất kỳ thứ gì, kể cả các tool cần để hoàn tác thay đổi. Nếu bắt buộc phải chạy một binary mới hơn trên host cũ, hãy unpack glibc mới hơn vào một thư mục riêng và khởi động chương trình đó thông qua loader riêng bằng --library-path. Cách này chỉ ảnh hưởng đến process đó. Rebuild với glibc cũ hơn vẫn là lựa chọn không khiến bạn gặp bất ngờ sau 6 tháng.