Một trang tải xuống nói 32-bit, tệp rơi xuống một Raspberry Pi và bộ cài thất bại với thông báo không nêu tên bất kỳ phần hữu ích nào của vấn đề. Hai tệp thực thi hoàn toàn khác nhau đều được tính là 32-bit theo nghĩa ELF, và chỉ một trong số chúng có thể chạy trên bo mạch đó. Trường lớp là một sự thật, trường máy là một sự thật khác, và tên tệp không cho bạn biết cả hai một cách đáng tin cậy. Hãy đọc tiêu đề trước khi đổi thư viện hoặc thử một máy chủ gương khác.

Lớp cho biết kích thước từ, máy cho biết tập lệnh

Tài liệu tham chiếu ELF của Linux định nghĩa trường lớp và trường máy trong tiêu đề tệp, và cả hai trả lời những câu hỏi khác nhau. Lớp cho biết tệp dùng dạng 32-bit hay 64-bit; máy cho biết nó được dựng cho tập lệnh nào. Một bản dựng x86 32-bit và một bản dựng ARM 32-bit đồng ý ở điểm thứ nhất và khác nhau ở điểm thứ hai. Đó là cách một nhãn hứa hẹn đúng kích thước từ vẫn giao mã mà bộ xử lý không thể giải mã. Giá trị thứ ba đáng đọc là trình thông dịch được yêu cầu, mà các tiêu đề chương trình nêu tên khi tệp nhị phân khai báo một trình.

readelf -h -- ./vendor-vpn
readelf -l -- ./vendor-vpn
readelf -d -- ./vendor-vpn | grep NEEDED

Lệnh đầu tiên in tiêu đề, lệnh thứ hai in các tiêu đề chương trình khi tệp có, và lệnh thứ ba liệt kê các đối tượng chia sẻ mà bộ nạp sẽ cần. Ghi lại lớp, máy và trình thông dịch cùng nhau, vì ba giá trị đó là toàn bộ câu hỏi tương thích ở lớp này. Không giá trị nào trong ba giá trị xuất hiện trên nút tải xuống, vì vậy phải kiểm tra tệp thay vì mô tả nó.

Nó yêu cầu nhân cấp trình thông dịch nào

Một tệp thực thi khai báo trình thông dịch yêu cầu nhân một đường dẫn bộ nạp cụ thể. Khi bộ nạp đó không có, việc khởi chạy thất bại dù tệp bạn nêu nằm ngay đó. Đây là điểm mà người ta kết luận rằng bản tải xuống bị hỏng, trong khi câu trả lời thật là một bộ nạp mà bản phân phối không cung cấp.

Khớp bộ nạp với hệ thống bạn thực sự chạy: phiên bản hệ điều hành, kiến trúc không gian người dùng và gói cung cấp bộ nạp. Nhân 64-bit chỉ có thể chạy không gian người dùng 32-bit khi không gian đó và bộ nạp của nó được cài đặt, nên khả năng của bộ xử lý không phải yếu tố quyết định. Một kiểm tra ngắn nêu tên trình thông dịch trên một dòng, và nó mất ít thời gian hơn một phiếu hỗ trợ. Tệp lệnh shell lại thất bại theo cách khác, vì trình thông dịch của nó được nêu ở dòng đầu tiên chứ không phải trong tiêu đề ELF, và đọc dòng đó không tốn gì.

file --brief ./vendor-vpn

Khớp bản tải xuống với kiến trúc gói

Kiến trúc gói của các bản phân phối mã hóa cùng sự khác biệt đó trong từ vựng của riêng chúng, và chính từ vựng đó là thứ mà tuyên bố hỗ trợ của nhà cung cấp tham chiếu. So sánh giá trị mà trình quản lý gói của bạn báo cáo với giá trị mà nhà cung cấp ghi lại, thay vì so sánh một nhãn tiếp thị với tên tệp. Các cặp gây rắc rối là amd64 so với arm64, và armhf so với armel, vì mỗi cặp trông có thể hoán đổi trong danh sách tải xuống. Tên tệp kết thúc bằng x64 hoặc ia32 mô tả mục tiêu dựng, không phải máy đang giữ nó.

Label on the downloadELF classe_machineInterpreter the kernel wantsHow it fails on the wrong host
amd64ELF64x86-64/lib64/ld-linux-x86-64.so.2Immediate exec failure on an ARM board
armhfELF32ARM/lib/ld-linux-armhf.so.3Loads on a soft-float system, then fails on a float ABI call
i386ELF32Intel 80386/lib/ld-linux.so.2Exec format error where no 32-bit loader package exists

Mỗi hàng là một trường hợp kích thước từ trông đúng mà mã vẫn hành xử sai, hoặc trường hợp nó khởi động rồi thất bại ở một lớp thấp hơn. Hãy đọc cột trình thông dịch như một yêu cầu cứng chứ không phải gợi ý, vì nhân phân giải đường dẫn đó trước khi bất kỳ phần mã nào của bạn chạy. Mô phỏng là một quyết định triển khai với những hệ quả riêng về hiệu năng và hỗ trợ, và nó không bao giờ được ngụ ý bởi một bộ xử lý quảng cáo kích thước từ rộng hơn.

dpkg --print-architecture

ENOEXEC và ENOENT là hai thất bại khác nhau

Giai đoạn khởi chạy báo cáo một trong hai lỗi, và chúng chỉ vào những vấn đề khác nhau. Đọc giá trị lỗi phân loại thất bại trước khi bạn chạy bất kỳ thứ gì khác.

ENOEXEC nghĩa là định dạng không được nhận ra: sai kiến trúc, sai lớp hoặc thứ gì đó hoàn toàn không phải tệp thực thi. ENOENT trên tệp ELF thường có nghĩa là thiếu trình thông dịch, dù tệp bạn yêu cầu vẫn tồn tại. Cùng ENOENT cũng có thể nghĩa là thiếu trình thông dịch của một tệp lệnh, vì thế dòng đầu tiên của tệp lệnh quan trọng. Dù thế nào, thông báo nêu tên lớp, và coi mọi «không tìm thấy» là thiếu cấu hình sẽ gửi cuộc điều tra sai hướng. Hãy trích dẫn giá trị lỗi trong phiếu, vì nó chịu được việc kể lại tốt hơn câu xung quanh.

Những gì không nên làm khi tệp nhị phân không khởi động

Ép một tệp nhị phân không được giải thích đi qua một lớp bọc shell không làm nó chạy. Đừng chạy trình kiểm tra phụ thuộc một cách tùy tiện trên tệp bạn không tin, vì việc chạy nó có thể thực thi mã từ tệp nhị phân trong một số tình huống. Đừng thêm liên kết tượng trưng của bộ nạp, đừng hoán đổi thư viện của máy chủ và đừng tải một kho lưu trữ cũ từ gương của bên thứ ba để lách thông báo. Mỗi việc trong số đó mở rộng bề mặt thay đổi mà không chạm tới sự không khớp mà tiêu đề đã nêu tên.

Khi liên hệ nhà cung cấp, hãy gửi giá trị chứ không phải câu chuyện: phiên bản hệ điều hành, kiến trúc gói, chuỗi lớp và máy, trình thông dịch được yêu cầu và dòng lỗi đầu tiên. Bộ đó giải quyết các câu hỏi hỗ trợ nhanh hơn ảnh chụp màn hình của một bộ cài thất bại. Các hiện vật cũ và đầu ra diễn đàn được ghi nhớ không phải là ma trận hỗ trợ hiện tại, và khi một tệp nhị phân gốc được nạp, hồ sơ, xác thực và định tuyến vẫn là công việc riêng.

Bài viết liên quan