Сторінка завантаження каже 32 біти, файл потрапляє на Raspberry Pi, і інсталятор падає з повідомленням, яке не називає жодної корисної частини проблеми. Два цілком різні виконувані файли обидва вважаються 32-бітними в сенсі ELF, і лише один із них може працювати на цій платі. Поле класу — один факт, поле машини — інший, а ім'я файлу надійно не повідомляє ні того, ні того. Прочитайте заголовок, перш ніж змінювати бібліотеку або пробувати інше дзеркало.

Клас каже розмір слова, машина — набір інструкцій

Довідник ELF для Linux визначає в заголовку файлу поле класу й поле машини, і ці два відповідають на різні питання. Клас каже, чи використовує файл 32-бітну або 64-бітну форму; машина каже, для якого набору інструкцій його зібрано. 32-бітна збірка x86 і 32-бітна збірка ARM збігаються в першому й розходяться в другому. Так етикетка, що обіцяє правильний розмір слова, все одно постачає код, який процесор не може декодувати. Третє значення, яке варто прочитати, — запитаний інтерпретатор, який заголовки програми називають, коли бінарний файл його оголошує.

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

Перша команда друкує заголовок, друга друкує заголовки програми, якщо вони є у файлі, а третя перелічує спільні об'єкти, які знадобляться завантажувачу. Записуйте клас, машину й інтерпретатор разом, бо ці три значення — усе питання сумісності на цьому рівні. Жодне з трьох не з'являється на кнопці завантаження, тому файл треба дослідити, а не описати.

Який інтерпретатор він просить у ядра

Виконуваний файл, що оголошує інтерпретатор, просить у ядра один конкретний шлях завантажувача. Коли цього завантажувача немає, запуск не вдається, хоча вказаний вами файл лежить просто там. Саме в цей момент люди вирішують, що завантаження пошкоджене, тоді як справжня відповідь — завантажувач, якого дистрибутив не постачає.

Зіставте завантажувач із системою, яку ви справді запускаєте: випуском ОС, архітектурою простору користувача й пакетом, що надає завантажувач. 64-бітне ядро може запускати 32-бітний простір користувача лише тоді, коли цей простір і його завантажувач встановлені, тож можливості процесора не є вирішальним чинником. Одна коротка перевірка називає інтерпретатор в одному рядку, і вона займає менше часу, ніж звернення до підтримки. Shell-скрипт падає вже інакше, бо його інтерпретатор указано в першому рядку, а не в заголовку ELF, і прочитати цей рядок нічого не коштує.

file --brief ./vendor-vpn

Зіставте завантаження з архітектурою пакета

Архітектури пакетів дистрибутивів кодують ту саму відмінність у власному словнику, і саме на цей словник посилається заява постачальника про підтримку. Порівняйте значення, яке повідомляє ваш менеджер пакетів, зі значенням, яке документує постачальник, замість того щоб порівнювати маркетингову етикетку з іменем файлу. Пари, що завдають клопоту, — amd64 проти arm64 і armhf проти armel, бо кожна пара у списку завантаження виглядає взаємозамінною. Ім'я файлу, що закінчується на x64 або ia32, описує ціль збірки, а не машину, яка його зберігає.

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

Кожен рядок — випадок, коли розмір слова виглядає правильним, а код усе одно поводиться неправильно, або коли він запускається й потім падає на рівень нижче. Читайте стовпець інтерпретатора як жорстку вимогу, а не як підказку, бо ядро розв'язує цей шлях до запуску будь-якої частини вашого коду. Емуляція — рішення про розгортання з власними наслідками для продуктивності й підтримки, і його ніколи не має на увазі процесор, що рекламує ширший розмір слова.

dpkg --print-architecture

ENOEXEC і ENOENT — різні збої

Етап запуску повідомляє про одну з двох помилок, і вони вказують на різні проблеми. Читання значення помилки класифікує збій до того, як ви запустите будь-що інше.

ENOEXEC означає, що формат не розпізнано: неправильна архітектура, неправильний клас або щось, що зовсім не є виконуваним файлом. ENOENT для файлу ELF зазвичай означає, що інтерпретатор відсутній, хоча запитаний файл існує. Той самий ENOENT може також означати відсутність інтерпретатора скрипта, тому перший рядок скрипта має значення. У будь-якому разі повідомлення називає рівень, а ставлення до кожного «не знайдено» як до відсутньої конфігурації скеровує розслідування в неправильний бік. Наведіть значення помилки в тікеті, бо воно краще переживає переказ, ніж речення навколо нього.

Чого не робити, коли бінарний файл не запускається

Проштовхування нез'ясованого бінарного файлу через обгортку shell не змушує його працювати. Не запускайте перевірку залежностей легковажно на файлі, якому не довіряєте, бо її запуск у деяких обставинах може виконати код із бінарного файлу. Не додавайте символьні посилання завантажувача, не підміняйте бібліотеки хоста й не завантажуйте старий архів із дзеркала третьої сторони, щоб обійти повідомлення. Кожне з цього розширює поверхню зміни, не торкаючись невідповідності, яку заголовок уже назвав.

Звертаючись до постачальника, надсилайте значення, а не історію: випуск ОС, архітектуру пакета, рядки класу й машини, запитаний інтерпретатор і перший рядок помилки. Цей набір розв'язує питання підтримки швидше, ніж знімок екрана інсталятора, що падає. Старі артефакти й пам'ятні виводи форумів не є актуальною матрицею підтримки, а після завантаження нативного бінарного файлу профіль, автентифікація й маршрутизація залишаються окремою роботою.

Схожі статті