Поиск по сайту:

Как работать с зависимостями общих объектов (библиотек) в Linux


Ошибка при загрузке разделяемых библиотек: страшная ошибка, с которой рано или поздно столкнется каждый пользователь Linux. Что-то пошло не так с общими объектными зависимостями (библиотеками), используемыми исполняемым файлом. Узнайте, как исправить такие проблемы и многое другое!

Что такое зависимость общего объекта?

Общий объект (также называемый библиотекой) — это двоичный файл (обычно не исполняемый напрямую), используемый несколькими программами/приложениями в экземпляре Linux. Такие библиотеки часто устанавливаются на уровне операционной системы и являются общими (отсюда и название общий объект или библиотеки) для использования одним или несколькими (и даже многими) непосредственно исполняемыми приложениями. .

Например, для программы, которая позволяет сжимать файлы, может потребоваться библиотека bz2 (bzip2) libbz2.so.1.0. Термин библиотека чаще используется в кругах Linux и является предпочтительным для профессионалов, хотя технически общий объектобщая библиотека) правильный. Также интересно отметить, что расширение имени файла .so, используемое во многих библиотеках, означает общий объект!

Исполняемый файл может иметь ноль, одну или множество библиотек, от которых он зависит. Чем меньше библиотек, тем больше (при обновлении операционной системы, например) будет совместимость. Чем больше библиотек, тем выше вероятность того, что рано или поздно какая-то библиотечная зависимость сломается. По этой же причине поставщики приложений иногда решают выпускать статически скомпилированные двоичные файлы, а не динамически скомпилированные двоичные файлы.

Разница между статически и динамически скомпилированными двоичными файлами проста, но имеет далеко идущие последствия. Статически скомпилированный двоичный файл имеет библиотеки (доступные в системе разработчика во время компиляции), скомпилированные в результирующий двоичный/исполняемый файл. Динамически скомпилированный двоичный файл будет использовать библиотеки, установленные, доступные и совместно используемые в системе пользователя.

Как вы можете сразу увидеть, это потребует от пользователя установки любых таких необходимых зависимостей, если только об этом не позаботится операционная система или система управления пакетами поставщика приложения и детали. Вот почему запуск простой команды, такой как sudo apt install ...some_app..., часто приводит к одновременной установке набора других связанных вещей (например, необходимых библиотек).

Как статическая, так и динамическая компиляция имеют свои плюсы и минусы. Например, если вы используете статическую компиляцию, а библиотека, которую вы включили в свой программный пакет (с точки зрения поставщика программного обеспечения), теперь имеет ошибку безопасности или критическое обновление, это, вероятно, означает, что вам придется перевыпустить ваш программный пакет, даже если в вашем коде ничего не изменилось.

Но опять же, полагаться на пользователя для установки библиотек, особенно для сложных программ, или когда требуется самокомпиляция программного обеспечения, с осознанием того, что конечные пользователи часто борются с такими вещами, также не идеально. Это сложная область, и этот вопрос часто обсуждался.

Для целей этой статьи мы рассмотрим разделяемые библиотеки в связи с программой, которая была динамически скомпилирована, как это часто бывает с программами/исполняемыми файлами/инструментами операционной системы. Со статически скомпилированными программами (которые менее распространены) сообщение об ошибке типа «Ошибка при загрузке разделяемых библиотек» маловероятно, так как библиотеки включены в исполняемый файл, если только программа не является частично динамической и включает только ограниченный набор встроенных библиотек. в статических библиотеках.

Ошибка при загрузке общих библиотек!

Давайте на время переключимся в режим root (используя sudo su) и изучим, как работают разделяемые библиотеки, когда речь идет о таком инструменте, как /usr/bin/zip, который включен или может быть установлен в основных дистрибутивах Linux.

Здесь мы изменили каталоги на /usr/bin и проверили наличие программы zip/binary/executable. Обнаружив его присутствие, мы затем проверили версию, вызвав ее с помощью --version и взяв только две верхние строки вывода, передав вывод (используя |), чтобы избежать длинный вывод, заданный в противном случае.

Наконец, мы использовали инструмент ldd (программа, которая печатает зависимости общих объектов), чтобы узнать, какие библиотеки требуются для исполняемого файла. Как мы видим, программе требуются четыре разделяемые библиотеки. Список требуемых библиотек обычно имеет формат требуемой библиотеки, за которым следует путь, по которому названная библиотека уже была найдена.

Для некоторых библиотек верхнего уровня или специальных библиотек уровня ОС (например, linux-vdso.so.1) такой путь не отображается. Однако, если для какой-либо записи не отображается ошибка, вы знаете, что она в порядке и доступна (или предпочтительнее). На самом деле linux-vdso.so.1 – это специальный виртуальный общий объект/библиотека, внедряемый в каждый процесс ядром Linux, для которого нет физического файла на диске. Это сделано для того, чтобы сделать системные вызовы более эффективными.

Итак, давайте немного сломаем ситуацию и переименуем одну из необходимых библиотек, чтобы она больше не могла автоматически обнаруживаться двоичным файлом:

Как видите, здесь мы переименовали/переместили файл из /lib/x86_64-linux-gnu/libbz2.so.1.0 в /lib/x86_64-linux-gnu/libbz2. так.1.0.НЕ ПРИСУТСТВУЕТ. Это сломало наше zip-приложение, и когда мы пытаемся запустить его, мы получаем ужасную ошибку при загрузке общих библиотек. Однако, если присмотреться, сообщение об ошибке на самом деле довольно описательное:

zip: error while loading shared libraries: libbz2.so.1.0: cannot open shared object file: No such file or directory

Опытный ИТ-инженер всегда будет тщательно просматривать любые журналы и выходные данные/информацию программы, представленные ему или ей, прежде чем звонить по проблеме. Это также окупится и здесь, так как требуемый файл ясно показан, libbz2.so.1.0, а также ясно показана проблема. Там Нет такого файла или каталога. Другими словами, libbz2.so.1.0 отсутствует!

Мы также можем проверить то же самое с помощью ldd, как видно на изображении выше. Четкий libbz2.so.1.0 => not found помогает нам понять, что происходит. Как только мы ясно понимаем, как динамически скомпилированные двоичные файлы (большинство двоичных файлов в операционной системе скомпилированы таким образом) загружают и требуют библиотек, и как определить, отсутствуют ли какие-либо из них (или о чем сообщается через сообщение об ошибке), все становится не так. не выглядеть так сложно больше.

Более того, как только мы узнаем имя требуемой библиотеки, быстрый поиск в вашей любимой поисковой системе покажет дополнительный пакет, который необходимо установить (или переустановить), чтобы получить требуемое имя библиотеки. Довольно часто имя пакета может быть истолковано даже непосредственно из имени библиотеки. Однако в этом случае имя библиотеки времени выполнения немного смещено.

Существует два типа библиотек — библиотеки времени выполнения и библиотеки разработки. В этом случае имя пакета, содержащего библиотеку libbz2.so.1.0 – это, скорее всего, bzip2, и попытка удаления, скорее всего, приведет к поломке различных других элементов, как видно из длинный список программ, которые будут удалены при попытке удалить или очистить пакет bzip2.

Второй тип библиотеки — это библиотека разработки. Они часто требуются при попытке скомпилировать программы и часто даже более тесно связаны с их реальными именами файлов библиотек. Например, в Ubuntu просто возьмите имя библиотеки и добавьте -dev. Например, если мы хотим установить пакет разработки, связанный с пакетом libbz2.so.1.0, мы можем посмотреть на установку libbz2-dev:

Поскольку эта библиотека разработки не имеет прямого отношения к нашей библиотеке времени выполнения libbz2.so.1.0, полезно знать синтаксис именования большинства имен пакетов разработки в Ubuntu (префикс lib и суффикс -dev с именем библиотеки между ними) для тех случаев, когда требуется определенная библиотека разработки (что чаще всего необходимо при компиляции программного обеспечения).

Кроме того, предположим, что какая-то библиотека каким-то образом вышла из строя. В этом случае одним из самых простых быстрых исправлений является очистка библиотеки командой sudo apt purge your_library_name (которая полностью очистит переданную библиотеку/программу) с последующей переустановкой с помощью sudo apt установите команду your_library_name.

И когда вы сталкиваетесь с ситуацией, похожей на описанную выше, когда удаление библиотеки времени выполнения требует удаления/очистки основной программы, и когда такая очистка/удаление занимает слишком большую часть операционной системы или может повлиять на слишком многие другие вещи, вы вместо этого можно использовать вариант переустановки:

sudo apt reinstall bzip2

Однако это не всегда так просто, хотя знание вышеизложенного (и особенно соглашения об именовании с точки зрения добавления -dev) чрезвычайно помогает при устранении неполадок и часто позволяет решить проблему сразу.

Также очень помогает знание того, как библиотеки можно проверять с помощью ldd, и, наконец, понимание того, что библиотека — это просто исполняемый (хотя и не напрямую) файл .so, который живет в подкаталоге /lib или в /usr/lib или других подобных каталогах.

Иногда библиотеки и/или пакеты конфликтуют друг с другом, или для определенных пакетов требуются определенные версии библиотек, или для определенных библиотек требуются другие библиотеки в определенных версиях. Да, это становится немного сложным. Также довольно легко, когда это становится таким сложным, немного испортить систему. Иногда даже вполне возможно полностью сломать установку операционной системы из-за перемещения слишком важной библиотеки и т. д.

Часто несколько безопаснее создать символическую ссылку (виртуальную ссылку с заданным именем файла, ссылающуюся на другой существующий файл или саму другую символическую ссылку, которая, в свою очередь, указывает на реальный файл) для отсутствующей библиотеки в более старой версии, например , и указывая эту символическую ссылку на последнюю установленную версию. Это не всегда срабатывает, но на всякий случай симлинк можно удалить, надеюсь, это будет безопаснее (при условии, что такого симлинка или файла с таким именем ранее не существовало).

Лучший способ устранить эти более сложные проблемы — всегда сначала использовать решение на основе apt (или аналогичного инструмента управления пакетами в вашей операционной системе). На этом этапе вы также захотите прочитать, как использовать dkpg для исправления apt, так как он показывает вам более детальный способ управления пакетами (хотя будьте осторожны, поскольку больший контроль подразумевает большую ответственность!).

Если ничего не помогает, попробуйте создать символическую ссылку или даже вручную добавить файл библиотеки. (Пожалуйста, трижды убедитесь, что любой загруженный файл не содержит вирусов, например, проверив его с помощью VirusTotal, и всегда лучше использовать репозитории, предоставленные поставщиком Linux, для загрузки двоичных файлов.)

В крайнем случае вы также можете найти библиотеку в соседней операционной системе Linux. Например, исполняемый файл Ubuntu будет работать на Mint и наоборот. Копирование библиотеки с другого компьютера, который у вас есть, также иногда является жизнеспособным подходом.

Подведение итогов

Детальное управление библиотекой — это навык, которому нужно учиться всю жизнь. Это почти искусство. В этой статье представлена основная информация/ноу-хау и инструменты для использования, а также перечислены некоторые более сложные предложения по устранению неполадок, когда что-то становится неясным, и рано или поздно они будут, если вы часто используете Linux, который регулярно устанавливает пакеты.

Когда вы в следующий раз увидите ошибку «Ошибка при загрузке общих библиотек» на вашем компьютере с Linux, вы будете лучше подготовлены к пониманию того, откуда может возникнуть проблема, с помощью такого инструмента, как ldd, как описано в этой статье. Мы также рассмотрели статические и динамически скомпилированные двоичные файлы, а также то, как совместно используемые или встроенные библиотеки подходят и работают с обоими.

Если вам понравилась эта статья, вы также можете прочитать статью о dpkg, указанную выше, а также о том, как добавить вселенную, мультивселенную и ограниченные репозитории в Ubuntu.