RPM-repair: различия между версиями
Klark (обсуждение | вклад) |
Klark (обсуждение | вклад) |
||
(не показано 14 промежуточных версий этого же участника) | |||
Строка 1: | Строка 1: | ||
'''rpmrepair: починка сторонних RPM путём перепаковки''' | '''rpmrepair: починка сторонних RPM путём перепаковки''' | ||
При установке сторонних пакетов, собранных не для соответствующего репозитория Альт, могут возникать проблемы несовместимости со штатным менеджером пакетов rpm, могут быть допущены ошибки в | При установке сторонних пакетов, собранных не для соответствующего репозитория Альт, могут возникать проблемы несовместимости со штатным менеджером пакетов rpm, могут быть допущены ошибки в скриптлетах пакета, могут быть неверно расставлены зависимости. Самый простой способ перепаковки предлагает утилита '''rpmrepair'''. Для её использования не требуются привилегии суперпользователя. В данном случае мы рассматриваем получение нового RPM не как процесс сборки из исходников. Бинарный результат у нас уже есть, с ним уже нельзя ничего сделать. Мы просто исправляем ошибки упаковки и рассматриваем RPM как архивный файл с метаданными, что позволит в дальнейшем при установке пакета отказаться от использования таких опций RPM, как '''--nodeps''', '''--noscripts''', '''--ignorearch'''. | ||
== Симптом == | == Симптом == | ||
Строка 29: | Строка 29: | ||
== Получение справки == | == Получение справки == | ||
<pre> | <pre> | ||
$ rpmrepair --help | |||
Usage: rpmrepair [<options>...] [--] [<package.rpm>...] | Usage: rpmrepair [<options>...] [--] [<package.rpm>...] | ||
Строка 65: | Строка 66: | ||
== Временный каталог == | == Временный каталог == | ||
Поскольку в дистрибутивах Альт TMPDIR обычно настроен на TMPFS (временные файлы создаются в оперативной памяти), а объём перепаковываемых RPM'ов может оказаться довольно большим, по умолчанию программа изменяет текущий TMPDIR на '''~/tmp''' и вся работа выполняется в домашнем каталоге пользователя. Данное поведение можно изменить опцией '''--notemp'''. В этом случае перепаковка будет выполняться на TMPFS. В любом случае надо иметь ввиду, что при выполнении '''rpm -bb''' раздел, на котором выполняется перепаковка должен быть смонтирован с опцией '''exec'''. В некоторых дистрибутивах Альт по умолчанию разделы '''/tmp''' и '''/home''' монтируются с '''noexec''', следовательно до начала перепаковки их нужно перемонтировать: | Поскольку в дистрибутивах Альт TMPDIR обычно настроен на TMPFS (временные файлы создаются в оперативной памяти), а объём перепаковываемых RPM'ов может оказаться довольно большим, по умолчанию программа изменяет текущий TMPDIR на '''~/tmp''' и вся работа выполняется в домашнем каталоге пользователя. Данное поведение можно изменить опцией '''--notemp'''. В этом случае перепаковка будет выполняться на TMPFS. В любом случае надо иметь ввиду, что при выполнении '''rpm -bb''' раздел, на котором выполняется перепаковка, должен быть смонтирован с опцией '''exec'''. В некоторых дистрибутивах Альт по умолчанию разделы '''/tmp''' и '''/home''' монтируются с '''noexec''', следовательно до начала перепаковки их нужно перемонтировать: | ||
<pre> | <pre> | ||
$ su- | $ su- | ||
Строка 72: | Строка 73: | ||
</pre> | </pre> | ||
В противном случае в процессе работы вы увидите ошибку, что операция не позволена. | В противном случае в процессе работы вы увидите ошибку, что операция не позволена. | ||
== Степень починки == | |||
'''rpmrepair --nodeps''' без дополнительных манипуляций практически гарантированно создаст RPM, который можно будет установить в систему. Конечно не факт, что упакованное ПО при этом заработает. Если же рабочий RPM получается с использованием '''rpmrepair --repair --scripts''' без дополнительных манипуляций, это намного лучше. Ключ '''--repair''' включает все стандартные очень жёсткие проверки альтовой сборочницы, включается максимальный поиск зависимостей и провайдсов, отделяются отладочные символы. Пробуйте разные варианты с индивидуальной RPM'кой, если не хотите вдаваться в детали. | |||
== Целевая архитектура == | == Целевая архитектура == | ||
Строка 90: | Строка 95: | ||
</pre> | </pre> | ||
== | == Перенос и исправление скриптов == | ||
В сторонних и проприетарных RPM'ках могут находиться скрипты, зачастую вредные или с ошибками. Никто не проверял их на совместимость с ОС Альт, поэтому такие скрипты по умолчанию не переносятся в перепакованные RPM'ки. Нужно самостоятельно извлечь их, посмотреть, что они делают, и, если требуется, создать на их основе правильные скрипты для пред/пост-установки/удаления. Находясь в каталоге с исходным RPM сделать это можно командой: | В сторонних и проприетарных RPM'ках могут находиться скрипты, зачастую вредные или с ошибками. Никто не проверял их на совместимость с ОС Альт, поэтому такие скрипты по умолчанию не переносятся в перепакованные RPM'ки. Нужно самостоятельно извлечь их, посмотреть, что они делают, и, если требуется, создать на их основе правильные скрипты для пред/пост-установки/удаления. Находясь в каталоге с исходным RPM сделать это можно командой: | ||
<pre>$ rpm -qp --scripts <package.rpm> > ИМЯ-ПАКЕТА. | <pre>$ rpm -qp --scripts <package.rpm> > ИМЯ-ПАКЕТА.scripts</pre> | ||
Отредактированный файл '''ИМЯ-ПАКЕТА. | Отредактированный файл '''ИМЯ-ПАКЕТА.scripts''' сам затянется в перепакованный RPM при запуске '''rpmrepair'''. Удалять и изменять строки типа "postinstall scriplet (through ...):" на соответствующие "%pre"/"%post"/итд... необязательно. Ключом '''--scripts''' можно включить автоматическое перекладывание скриптлетов из исходных RPM "как есть", при этом отредактированным вариантам всё равно отдаётся предпочтение. | ||
== Другие особенности == | == Другие особенности == | ||
Строка 103: | Строка 108: | ||
== Пример использования == | == Пример использования == | ||
Возьмём за основу поломанную сборку сервера 1C v8.3.17.1549 | Возьмём за основу поломанную сборку сервера 1C v8.3.17.1549 -- приведённые ниже строки можно вставить в скрипт или скопировать на выполнение прямо в консоль. | ||
<pre> | <pre> | ||
cd ~/ | cd ~/ | ||
Строка 118: | Строка 123: | ||
echo "/opt/1C/v8.3/x86_64/ExtDst" >1C_Enterprise83-server.dirs | echo "/opt/1C/v8.3/x86_64/ExtDst" >1C_Enterprise83-server.dirs | ||
for rpm in 1C_Enterprise83*.rpm; do | for rpm in 1C_Enterprise83*.rpm; do | ||
name="$(rpm -qp --qf "%{NAME}")" | name="$(rpm -qp --qf "%{NAME}" "$rpm")" | ||
rpm -qp --requires "$rpm" |grep -E ^1C_ |sed -E 's,^,Requires: ,g' >"$name.deps" | rpm -qp --requires "$rpm" |grep -E ^1C_ |sed -E 's,^,Requires: ,g' >"$name.deps" | ||
[ -s "$name.deps" ] || rm -f "$name.deps" | [ -s "$name.deps" ] || rm -f "$name.deps" | ||
Строка 124: | Строка 129: | ||
rpmrepair --nodeps --scripts | rpmrepair --nodeps --scripts | ||
</pre> | </pre> | ||
Перепаковка займёт порядка 4.5 минут. В подкаталоге repacked окажется семь RPM-файлов на 360Мб. | Перепаковка займёт порядка '''4.5 минут'''. В подкаталоге '''repacked''' окажется семь RPM-файлов на '''360Мб'''. Теперь установим перепакованные пакеты: | ||
<pre> | <pre> | ||
$ su- | $ su- | ||
Строка 139: | Строка 144: | ||
ls: невозможно получить доступ к /opt/1C/: Нет такого файла или каталога | ls: невозможно получить доступ к /opt/1C/: Нет такого файла или каталога | ||
</pre> | </pre> | ||
То есть, дезинсталляция выполняется "без хвостов". | |||
== Получение полуфабриката == | |||
Ключ '''--noclean''' предписывает не удалять промежуточные результаты работы. Таким образом над распакованным каталогом и созданным спеком можно провести дополнительную работу, не предусмотренную данной программой (например, удалить лишние файлы, пропатчить эльфы, итд...), после чего упаковать каталог в тарбол и запустить '''rpm -bb''' вручную. | |||
== Отладка == | == Отладка и отправка сообщений об ошибках == | ||
Для отправки в Bugzilla сообщения об ошибке следует запустить на одиночном RPM-пакете, перепаковка которого выполняется с ошибками, команду: | Для отправки в Bugzilla сообщения об ошибке следует запустить на одиночном RPM-пакете, перепаковка которого выполняется с ошибками, команду: | ||
<pre>$ /bin/bash - | <pre>$ /bin/bash -eux /usr/bin/rpmrepair --noclean [другие_опции] <package.rpm> 2>&1 |tee ИМЯ-ПАКЕТА.log</pre> | ||
Получившийся отчёт вместе с файлами *.deps, *.dirs, *.scripts из текущего каталога и всеми файлами из временного каталога (кроме подкаталога make-tar) приложить к сообщению об ошибке. | Получившийся отчёт вместе с соответствующими файлами '''*.deps''', '''*.dirs''', '''*.scripts''' из текущего каталога и всеми файлами из временного каталога (кроме подкаталога '''make-tar''') приложить к сообщению об ошибке. | ||
Текущая версия от 01:10, 11 августа 2020
rpmrepair: починка сторонних RPM путём перепаковки
При установке сторонних пакетов, собранных не для соответствующего репозитория Альт, могут возникать проблемы несовместимости со штатным менеджером пакетов rpm, могут быть допущены ошибки в скриптлетах пакета, могут быть неверно расставлены зависимости. Самый простой способ перепаковки предлагает утилита rpmrepair. Для её использования не требуются привилегии суперпользователя. В данном случае мы рассматриваем получение нового RPM не как процесс сборки из исходников. Бинарный результат у нас уже есть, с ним уже нельзя ничего сделать. Мы просто исправляем ошибки упаковки и рассматриваем RPM как архивный файл с метаданными, что позволит в дальнейшем при установке пакета отказаться от использования таких опций RPM, как --nodeps, --noscripts, --ignorearch.
Симптом
# rpm -ivh 1C_Enterprise83-ws-nls-8.3.17-1549.x86_64.rpm ... rpmlib(FileDigests) <= 4.6.0-1 нужен для 1C_Enterprise83-ws-nls-8.3.17-1549
Установка
$ su- # apt-get update # apt-get install rpmrepair
Если в нужный репозиторий пакет ещё не попал, существует альтернативный способ установки:
$ su- # apt-repo test 255700
Зависимости у rpmrepair минимальны -- rpm-build, rsync и fakeroot. Перечисленные пакеты нужны только на момент перепаковки, для работы перепакованных пакетов они не требуются.
Ответственный упаковщик
Упаковщиком созданных пакетов (PACKAGER) по умолчанию будет тот, кто упаковал исходный пакет. Если данное поле не указано, им будет системный упаковщик по умолчанию -- берётся из файла ~/.rpmmacros или из командной строки (--packager). Если и это не будет указано, ответственным за перепакованный пакет по умолчанию ставится автор rpmrepair.
Получение справки
$ rpmrepair --help Usage: rpmrepair [<options>...] [--] [<package.rpm>...] Options: -a, --noarch Use noarch data packaging method. -n, --nodeps Drop all dependencies in created RPM. -p, --packager Set default PACKAGER name and e-mail. -r, --repair Try to repair packaging errors. -s, --scripts Add scriptlets from source RPM. -t, --notemp Do not change TMPDIR at startup. -N, --noclean Do not cleanup work files at exit. -v, --version Show this program version and exit. -h, --help Show this help message and exit. Example: rpmrepair -p "John Doe <agent007@example.org>" Will be repacked all RPM's in the current directory, results will be saved to the 'repacked' sub-directory. All pre/post/preun/postun scripts will be dropped. User manual: https://www.altlinux.org/RPM-repair (ru) Please, report bugs to https://bugzilla.altlinux.org/
Принцип действия
Программа распаковывает исходный RPM через rpm2cpio и cpio, упаковывает в архив .tar, извлекает метаданные пакета и создаёт SPEC, на его основе через rpm -bb собирается новый RPM-пакет. При этом отрываются зависимости на rpmlib(...), а если дополнительно указать параметр --nodeps, то из исходных пакетов вообще никакие зависимости не будут перенесены в перепакованные визави. В качестве аргумента можно указать один или несколько RPM, каждый перепаковывается независимо. Если не указать ни одного пакета, будет предпринята попытка перепаковать все RPM-пакеты в текущем каталоге. Только при успешном завершении в текущем каталоге создаётся подкаталог repacked, в который помещается результат работы. По умолчанию временные файлы удаляются, независимо от результата, но опция --noclean позволяет их оставить в отладочных целях.
Предупреждения
До начала работы из текущего каталога будет удалён подкаталог repacked. Также будет удалён каталог ~/RPM со всем содержимым. Сохраняйте свои RPM'ки заблаговременно! Следует иметь ввиду: вендор исходного RPM-пакета не отвечает за получившийся перепакованный результат, поэтому ему следует адресовать рекламации только по исходному пакету. За перепакованный результат вообще никто не может отвечать, вы перепаковываете только на свой страх и риск.
Временный каталог
Поскольку в дистрибутивах Альт TMPDIR обычно настроен на TMPFS (временные файлы создаются в оперативной памяти), а объём перепаковываемых RPM'ов может оказаться довольно большим, по умолчанию программа изменяет текущий TMPDIR на ~/tmp и вся работа выполняется в домашнем каталоге пользователя. Данное поведение можно изменить опцией --notemp. В этом случае перепаковка будет выполняться на TMPFS. В любом случае надо иметь ввиду, что при выполнении rpm -bb раздел, на котором выполняется перепаковка, должен быть смонтирован с опцией exec. В некоторых дистрибутивах Альт по умолчанию разделы /tmp и /home монтируются с noexec, следовательно до начала перепаковки их нужно перемонтировать:
$ su- # mount -o remount,exec /home # mount -o remount,exec /tmp
В противном случае в процессе работы вы увидите ошибку, что операция не позволена.
Степень починки
rpmrepair --nodeps без дополнительных манипуляций практически гарантированно создаст RPM, который можно будет установить в систему. Конечно не факт, что упакованное ПО при этом заработает. Если же рабочий RPM получается с использованием rpmrepair --repair --scripts без дополнительных манипуляций, это намного лучше. Ключ --repair включает все стандартные очень жёсткие проверки альтовой сборочницы, включается максимальный поиск зависимостей и провайдсов, отделяются отладочные символы. Пробуйте разные варианты с индивидуальной RPM'кой, если не хотите вдаваться в детали.
Целевая архитектура
Независимо от указанной в названии файла пакета архитектуры, упаковка нового RPM-пакета выполняется для текущей архитектуры. Если исходный RPM-пакет на самом деле содержит только архитектурно-независимые файлы, есть возможность упаковать его в пакет *.noarch.rpm, просто добавив ключ --noarch при запуске rpmrepair.
Исправление зависимостей
Независимо от наличия или отсутствия ключа --nodeps, можно добавить свой "кусок спека" при перепаковке. Для этого достаточно сложить рядом с RPM-пакетом файл ИМЯ-ПАКЕТА.deps. Здесь и далее "ИМЯ-ПАКЕТА" можно получить командой:
$ rpm -qp --qf "%{NAME}\n" <package.rpm>
В файле ИМЯ-ПАКЕТА.deps можно указывать такие поля, как Requires:, Obsoletes:, Conflicts: и Provides:. Провайдсы из исходных RPM не переносятся никогда, так что по умолчанию пакет будет провайдить только сам себя. Чтобы выяснить, что требует и что провайдит исходный пакет, а затем исправить это, выполните пару команд:
$ rpm -qp --requires <package.rpm> |sed -E ',^,Requires: ,g' > ИМЯ-ПАКЕТА.deps $ rpm -qp --provides <package.rpm> |sed -E ',^,Provides: ,g' >> ИМЯ-ПАКЕТА.deps
Перенос и исправление скриптов
В сторонних и проприетарных RPM'ках могут находиться скрипты, зачастую вредные или с ошибками. Никто не проверял их на совместимость с ОС Альт, поэтому такие скрипты по умолчанию не переносятся в перепакованные RPM'ки. Нужно самостоятельно извлечь их, посмотреть, что они делают, и, если требуется, создать на их основе правильные скрипты для пред/пост-установки/удаления. Находясь в каталоге с исходным RPM сделать это можно командой:
$ rpm -qp --scripts <package.rpm> > ИМЯ-ПАКЕТА.scripts
Отредактированный файл ИМЯ-ПАКЕТА.scripts сам затянется в перепакованный RPM при запуске rpmrepair. Удалять и изменять строки типа "postinstall scriplet (through ...):" на соответствующие "%pre"/"%post"/итд... необязательно. Ключом --scripts можно включить автоматическое перекладывание скриптлетов из исходных RPM "как есть", при этом отредактированным вариантам всё равно отдаётся предпочтение.
Другие особенности
Данный способ перепаковки не предусматривает "чистого" удаления, т.к. по умолчанию каталоги не принадлежат к какому-либо пакету. Следовательно, при удалении таких пакетов придётся "хвосты" (пустые каталоги) удалять вручную. Избавить от такой необходимости пользователей перепакованного RPM можно лишь добавив информацию о принадлежности каталогов конкретному пакету. Установить принадлежность для единственного пакета достаточно легко, для целой пачки пакетов -- задача непростая, но тоже решаемая. Просто перечислите все каталоги, относящиеся к пакету, в файле с именем ИМЯ-ПАКЕТА.dirs и сложите его рядом. rpmrepair сам затянет это в создаваемый RPM. При этом надо иметь ввиду, что конкретный каталог не может принадлежать двум пакетам одновременно.
Пример использования
Возьмём за основу поломанную сборку сервера 1C v8.3.17.1549 -- приведённые ниже строки можно вставить в скрипт или скопировать на выполнение прямо в консоль.
cd ~/ tar -xf rpm64_8_3_17_1549.tar.gz cat >1C_Enterprise83-common.dirs <<EOF /opt/1C /opt/1C/v8.3 /opt/1C/v8.3/x86_64 /opt/1C/v8.3/x86_64/licenses /opt/1C/v8.3/x86_64/licenses/3rd_party /opt/1C/v8.3/x86_64/dmf /opt/1C/v8.3/x86_64/dmf/lib EOF echo "/opt/1C/v8.3/x86_64/ExtDst" >1C_Enterprise83-server.dirs for rpm in 1C_Enterprise83*.rpm; do name="$(rpm -qp --qf "%{NAME}" "$rpm")" rpm -qp --requires "$rpm" |grep -E ^1C_ |sed -E 's,^,Requires: ,g' >"$name.deps" [ -s "$name.deps" ] || rm -f "$name.deps" done rpmrepair --nodeps --scripts
Перепаковка займёт порядка 4.5 минут. В подкаталоге repacked окажется семь RPM-файлов на 360Мб. Теперь установим перепакованные пакеты:
$ su- # rpm -ivh /home/user/repacked/*.rpm
Обратите внимание на особенности удаления -- common удаляется в последнюю очередь:
# rpm -e $(rpm -qa |grep -E ^1C_ |grep -v 1C_Enterprise83-common-8.3.17-1549) Stopping 1C:Enterprise 8.3 server: Warning: server not running! OK # rpm -e 1C_Enterprise83-common-8.3.17-1549 # l /opt/1C/ ls: невозможно получить доступ к /opt/1C/: Нет такого файла или каталога
То есть, дезинсталляция выполняется "без хвостов".
Получение полуфабриката
Ключ --noclean предписывает не удалять промежуточные результаты работы. Таким образом над распакованным каталогом и созданным спеком можно провести дополнительную работу, не предусмотренную данной программой (например, удалить лишние файлы, пропатчить эльфы, итд...), после чего упаковать каталог в тарбол и запустить rpm -bb вручную.
Отладка и отправка сообщений об ошибках
Для отправки в Bugzilla сообщения об ошибке следует запустить на одиночном RPM-пакете, перепаковка которого выполняется с ошибками, команду:
$ /bin/bash -eux /usr/bin/rpmrepair --noclean [другие_опции] <package.rpm> 2>&1 |tee ИМЯ-ПАКЕТА.log
Получившийся отчёт вместе с соответствующими файлами *.deps, *.dirs, *.scripts из текущего каталога и всеми файлами из временного каталога (кроме подкаталога make-tar) приложить к сообщению об ошибке.
Enjoy! -;)