Установщик VPN говорит 32 бита: проверьте заголовок ELF
Размер слова не определяет набор инструкций. Порядок чтения класса, машины и интерпретатора, а затем запроса сборки, подходящей хосту.
Страница загрузки говорит 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 download | ELF class | e_machine | Interpreter the kernel wants | How it fails on the wrong host |
|---|---|---|---|---|
| amd64 | ELF64 | x86-64 | /lib64/ld-linux-x86-64.so.2 | Immediate exec failure on an ARM board |
| armhf | ELF32 | ARM | /lib/ld-linux-armhf.so.3 | Loads on a soft-float system, then fails on a float ABI call |
| i386 | ELF32 | Intel 80386 | /lib/ld-linux.so.2 | Exec format error where no 32-bit loader package exists |
Каждая строка — случай, когда размер слова выглядит правильным, а код всё равно ведёт себя неверно, или когда он запускается и затем падает на уровень ниже. Читайте столбец интерпретатора как жёсткое требование, а не как подсказку, потому что ядро разрешает этот путь до запуска любой части вашего кода. Эмуляция — решение о развёртывании с собственными последствиями для производительности и поддержки, и её никогда не подразумевает процессор, рекламирующий более широкий размер слова.
dpkg --print-architecture
ENOEXEC и ENOENT — разные сбои
Этап запуска сообщает об одной из двух ошибок, и они указывают на разные проблемы. Чтение значения ошибки классифицирует сбой до того, как вы запустите что-либо ещё.
ENOEXEC означает, что формат не распознан: неверная архитектура, неверный класс или нечто, вовсе не являющееся исполняемым файлом. ENOENT для файла ELF обычно означает, что интерпретатор отсутствует, хотя запрошенный файл существует. Тот же ENOENT может также означать отсутствие интерпретатора скрипта, поэтому первая строка скрипта имеет значение. В любом случае сообщение называет уровень, а отношение к каждому «не найдено» как к отсутствующей конфигурации направляет расследование в неверную сторону. Приведите значение ошибки в тикете, потому что оно лучше переживает пересказ, чем предложение вокруг него.
Чего не делать, когда бинарный файл не запускается
Проталкивание необъяснённого бинарного файла через обёртку shell не заставляет его работать. Не запускайте проверку зависимостей легкомысленно на файле, которому не доверяете, потому что её запуск в некоторых обстоятельствах может выполнить код из бинарного файла. Не добавляйте символические ссылки загрузчика, не подменяйте библиотеки хоста и не скачивайте старый архив с зеркала третьей стороны, чтобы обойти сообщение. Каждое из этого расширяет поверхность изменения, не касаясь несоответствия, которое заголовок уже назвал.
Обращаясь к поставщику, отправляйте значения, а не историю: выпуск ОС, архитектуру пакета, строки класса и машины, запрошенный интерпретатор и первую строку ошибки. Этот набор решает вопросы поддержки быстрее, чем снимок экрана падающего установщика. Старые артефакты и запомненные выводы форумов не являются актуальной матрицей поддержки, а после загрузки нативного бинарного файла профиль, аутентификация и маршрутизация остаются отдельной работой.