--- description: 'Продвинутые практики pkg-plist' next: books/porters-handbook/pkg-files params: path: /books/porters-handbook/plist/ prev: books/porters-handbook/flavors showBookMenu: 'true' tags: ["pkg-plist", "practices", "configuration"] title: 'Глава 8. Продвинутые практики pkg-plist' weight: 8 --- [[plist]] = Продвинутые практики pkg-plist :doctype: book :toc: macro :toclevels: 1 :icons: font :sectnums: :sectnumlevels: 6 :sectnumoffset: 8 :partnums: :source-highlighter: rouge :experimental: :images-path: books/porters-handbook/ ifdef::env-beastie[] ifdef::backend-html5[] :imagesdir: ../../../../images/{images-path} endif::[] ifndef::book[] include::shared/authors.adoc[] include::shared/mirrors.adoc[] include::shared/releases.adoc[] include::shared/attributes/attributes-{{% lang %}}.adoc[] include::shared/{{% lang %}}/teams.adoc[] include::shared/{{% lang %}}/mailing-lists.adoc[] include::shared/{{% lang %}}/urls.adoc[] toc::[] endif::[] ifdef::backend-pdf,backend-epub3[] include::../../../../../shared/asciidoctor.adoc[] endif::[] endif::[] ifndef::env-beastie[] toc::[] include::../../../../../shared/asciidoctor.adoc[] endif::[] [[plist-sub]] == Изменение содержимого [.filename]#pkg-plist# в зависимости от make-переменных Некоторые порты, в частности, порты `p5-`, должны менять содержимое своих файлов [.filename]#pkg-plist# в зависимости от того, с какими параметрами они были отконфигурированы (или в зависимости от версии языка `perl` в случае портов `p5-`). Чтобы облегчить этот процесс, любые вхождения ключевых слов `%%OSREL%%`, `%%PERL_VER%%` и `%%PERL_VERSION%%` в файле [.filename]#pkg-plist# будут заменяться соответствующими значениями. Значением `%%OSREL%%` является номер версии операционной системы (например, `4.9`). `%%PERL_VERSION%%` и `%%PERL_VER%%` обозначают полный номер версии `perl` (например, `5.8.9`). Некоторые другие `%%VARS%%`, имеющие отношение к файлам документации порта, описаны в crossref:makefiles[install-documentation,соответствующем разделе]. Если вам нужно сделать другие подстановки, вы можете указать в переменной `PLIST_SUB` список пар `VAR=VALUE`, и все вхождения `%%VAR%%` в файле [.filename]#pkg-plist# будут заменяться на значение _VALUE_. Например, если порт устанавливает множество файлов в подкаталоге, зависящем от версии, используйте заполнитель для версии, чтобы файл [.filename]#pkg-plist# не требовал перегенерации при каждом обновлении порта. Например, укажите: [.programlisting] .... OCTAVE_VERSION= ${PORTREVISION} PLIST_SUB= OCTAVE_VERSION=${OCTAVE_VERSION} .... в файле [.filename]#Makefile# и использовать `%%OCTAVE_VERSION%%` везде, где нужно указать номер версии в файле [.filename]#pkg-plist#. Таким образом, при обновлении порта вам не нужно будет менять десятки (а в некоторых случаях и сотни) строк в файле [.filename]#pkg-plist#. Если файлы устанавливаются по условию в зависимости от опций, установленных в порте, обычный способ обработки — это добавление префикса `%%OPT%%` для строк в [.filename]#pkg-plist#, которые нужны при включении опции, или `%%NO_OPT%%`, когда опция отключена, а также добавление `OPTIONS_SUB=yes` в [.filename]#Makefile#. Подробнее см. crossref:makefiles[options_sub,`OPTIONS_SUB`]. Например, если есть файлы, которые устанавливаются только при включении опции `X11`, и в [.filename]#Makefile# указано: [.programlisting] .... OPTIONS_DEFINE= X11 OPTIONS_SUB= yes .... В [.filename]#pkg-plist# укажите `%%X11%%` перед строками, которые устанавливаются только при включении опции, например: [.programlisting] .... %%X11%%bin/foo-gui .... Эта подстановка будет сделана между выполнением целей `pre-install` и `do-install`, посредством чтения файла [.filename]#PLIST# и записью в файл [.filename]#TMPPLIST# (по умолчанию это файл [.filename]#WRKDIR/.PLIST.mktmp#). Так что если ваш порт строит [.filename]#PLIST# на лету, делайте это во время или до выполнения цели `pre-install`. Кроме того, если вашему порту требуется отредактировать получающийся файл, делайте это в цели `post-install` изменением файла [.filename]#TMPPLIST#. Ещё один способ изменения списка упаковки порта основан на установке переменных `PLIST_FILES` и `PLIST_DIRS`. Значение каждой переменной рассматривается как список путей для записи в [.filename]#TMPPLIST# вместе с содержимым [.filename]#PLIST#. Хотя имена, перечисленные в `PLIST_FILES` и `PLIST_DIRS`, подлежат замене `%%_VAR_%%`, как описано выше, лучше использовать `${_VAR_}` напрямую. За исключением этого, имена из `PLIST_FILES` появятся в итоговом списке упаковки без изменений, тогда как к именам из `PLIST_DIRS` будет добавлен префикс `@dir`. Чтобы вступить в силу, `PLIST_FILES` и `PLIST_DIRS` должны быть установлены до записи [.filename]#TMPPLIST#, то есть в `pre-install` или ранее. Время от времени использования `OPTIONS_SUB` недостаточно. В таких случаях добавление специфичного `_TAG_` в `PLIST_SUB` внутри [.filename]#Makefile# со специальным значением `@comment` заставляет инструменты пакетирования игнорировать строку. Например, если некоторые файлы устанавливаются только при включённой опции `X11` и архитектуре `i386`: [.programlisting] .... .include .if ${PORT_OPTIONS:MX11} && ${ARCH} == "i386" PLIST_SUB+= X11I386="" .else PLIST_SUB+= X11I386="@comment " .endif .... [[plist-cleaning]] == Пустые каталоги [[plist-dir-cleaning]] === Очистка пустых каталогов При удалении порт должен удалить пустые каталоги, которые он создал. Большинство этих каталогов автоматически удаляются с помощью man:pkg[8], но для каталогов, созданных вне [.filename]#${PREFIX}#, или пустых каталогов требуется дополнительная работа. Обычно это делается добавлением строк `@dir` для таких каталогов. Подкаталоги должны быть удалены до удаления родительских каталогов. [.programlisting] .... [...] @dir /var/games/oneko/saved-games @dir /var/games/oneko .... [[plist-dir-empty]] === Создание пустых каталогов Пустые каталоги, созданные во время установки порта, требуют особого внимания. Они должны присутствовать при создании пакета. Если они не созданы кодом порта, создайте их в [.filename]#Makefile#: [.programlisting] .... post-install: ${MKDIR} ${STAGEDIR}${PREFIX}/some/directory .... Добавьте каталог в [.filename]#pkg-plist# так же, как и любой другой. Например: [.programlisting] .... @dir some/directory .... [[plist-config]] == Файлы конфигурации Если порт устанавливает файлы конфигурации в [.filename]#PREFIX/etc# (или в другое место), _не_ указывайте их в [.filename]#pkg-plist#. Это приведёт к тому, что `pkg delete` удалит файлы, которые были тщательно отредактированы пользователем, а повторная установка перезапишет их. Вместо этого устанавливайте образцы файлов с расширением [.filename]#filename.sample#. Макрос `@sample` автоматизирует этот процесс; подробности его работы см. в разделе crossref:plist[plist-keywords-sample, Расширение списка пакетов с помощью ключевых слов]. Для каждого образца файла добавьте строку в [.filename]#pkg-plist#: [.programlisting] .... @sample etc/orbit.conf.sample .... Если существует очень веская причина не устанавливать рабочий файл конфигурации по умолчанию, укажите только имя примера файла в [.filename]#pkg-plist#, без части `@sample` с последующим пробелом, и добавьте crossref:pkg-files[porting-message,сообщение], указывающее, что пользователь должен скопировать и отредактировать файл перед тем, как программа заработает. [TIP] ==== Когда порт устанавливает свою конфигурацию в подкаталоге [.filename]#${PREFIX}/etc#, используйте `ETCDIR`, который по умолчанию равен `${PREFIX}/etc/${PORTNAME}`. Это значение может быть переопределено в [.filename]#Makefile# порта, если для порта принято использовать другой каталог. Макрос `%%ETCDIR%%` будет использоваться вместо этого в [.filename]#pkg-plist#. ==== [NOTE] ==== Примеры конфигурационных файлов всегда должны иметь суффикс [.filename]#.sample#. Если по каким-то историческим причинам использование стандартного суффикса невозможно, или если примеры файлов взяты из другого каталога, используйте эту конструкцию: [.programlisting] .... @sample etc/orbit.conf-dist etc/orbit.conf .... или [.programlisting] .... @sample %%EXAMPLESDIR%%/orbit.conf etc/orbit.conf .... Формат: `@sample _файл-образец фактический-конфигурационный-файл_`. ==== [[plist-dynamic]] == Динамический или статический список упаковки _Статический список упаковки_ — это список упаковки, который доступен в Коллекции Портов или как файл [.filename]#pkg-plist# (с подстановкой переменных или без неё), или как встроенный в [.filename]#Makefile# через `PLIST_FILES` и `PLIST_DIRS`. Даже если содержимое было автоматически сгенерировано инструментом или целью в Makefile _до_ включения в Коллекцию портов коммиттером (например, с использованием `make makeplist`), такой список всё равно считается статическим, поскольку его можно посмотреть без необходимости загрузки или компиляции distfile. _Динамический список упаковки_ — это список упаковки, который генерируется во время компиляции порта на основе установленных файлов и каталогов. Невозможно изучить его до загрузки и компиляции исходного кода портированного приложения или после выполнения команды `make clean`. Хотя использование динамических списков упаковки не запрещено, сопровождающие должны использовать статические списки упаковки везде, где это возможно, поскольку это позволяет пользователям выполнять man:grep[1] по доступным портам для обнаружения, например, какой порт устанавливает определённый файл. Динамические списки должны быть использованы в основном для сложных портов, для которых изменения в списке упаковки кардинальным образом основаны на возможностях порта, настраиваемых параметрами, (и, таким образом, делая сопровождение статических списков упаковки невозможным), или портов, которые изменяют список упаковки на основе версии используемого им программного обеспечения (например, порты, которые порождают документы при помощи Javadoc). [[plist-autoplist]] == Автоматическое создание списка упаковки Сначала убедитесь, что порт почти готов, и отсутствует только файл [.filename]#pkg-plist#. Запуск команды `make makeplist` покажет пример для файла [.filename]#pkg-plist#. Вывод `makeplist` необходимо дважды перепроверять на корректность, так как он пытается автоматически угадать некоторые вещи и может ошибаться. Файлы конфигурации пользователя должны устанавливаться как [.filename]#filename.sample#, как описано в разделе crossref:plist[plist-config,Файлы конфигурации]. [.filename]#info/dir# не должен быть указан, а соответствующие строки [.filename]#install-info# должны быть добавлены, как указано в разделе crossref:makefiles[makefile-info,info-файлы]. Любые библиотеки, устанавливаемые портом, должны быть перечислены, как указано в разделе crossref:special[porting-shlibs,общие библиотеки]. [[plist-autoplist-regex]] === Расширение `PLIST_SUB` с помощью регулярных выражений Строки, которые нужно заменить, иногда должны быть очень конкретными, чтобы избежать нежелательных замен. Это распространённая проблема с короткими значениями. Для решения этой проблемы для каждого `_PLACEHOLDER_=_значение_` можно задать `PLACEHOLDER_regex=регулярное_выражение`, где `_регулярное_выражение_` более точно соответствует _значению_. [[plist-autoplist-regex-ex1]] .Использование PLIST_SUB с регулярными выражениями [example] ==== Порты Perl могут устанавливать архитектурно-зависимые файлы в специальное дерево. В FreeBSD для упрощения портирования это дерево называется `mach`. Например, порт, который устанавливает файл, чей путь содержит `mach`, может иметь эту часть строки пути заменённой неправильными значениями. Рассмотрим этот [.filename]#Makefile#: [.programlisting] .... PORTNAME= Machine-Build DISTVERSION= 1 CATEGORIES= devel perl5 MASTER_SITES= CPAN PKGNAMEPREFIX= p5- MAINTAINER= perl@FreeBSD.org COMMENT= Building machine WWW= https://search.cpan.org/dist/Machine-Build USES= perl5 USE_PERL5= configure PLIST_SUB= PERL_ARCH=mach .... Файлы, установленные портом: [.programlisting] .... /usr/local/bin/machine-build /usr/local/lib/perl5/site_perl/man/man1/machine-build.1.gz /usr/local/lib/perl5/site_perl/man/man3/Machine::Build.3.gz /usr/local/lib/perl5/site_perl/Machine/Build.pm /usr/local/lib/perl5/site_perl/mach/5.20/Machine/Build/Build.so .... Запуск `make makeplist` ошибочно создает: [.programlisting] .... bin/%%PERL_ARCH%%ine-build %%PERL5_MAN1%%/%%PERL_ARCH%%ine-build.1.gz %%PERL5_MAN3%%/Machine::Build.3.gz %%SITE_PERL%%/Machine/Build.pm %%SITE_PERL%%/%%PERL_ARCH%%/%%PERL_VER%%/Machine/Build/Build.so .... Измените строку `PLIST_SUB` в [.filename]#Makefile# на: [.programlisting] .... PLIST_SUB= PERL_ARCH=mach \ PERL_ARCH_regex=\bmach\b .... Теперь `make makeplist` правильно генерирует: [.programlisting] .... bin/machine-build %%PERL5_MAN1%%/machine-build.1.gz %%PERL5_MAN3%%/Machine::Build.3.gz %%SITE_PERL%%/Machine/Build.pm %%SITE_PERL%%/%%PERL_ARCH%%/%%PERL_VER%%/Machine/Build/Build.so .... ==== [[plist-keywords]] == Расширение списка пакетов, используя ключевые слова Все ключевые слова также могут принимать необязательные аргументы в скобках. Аргументами являются владелец, группа и режим доступа. Этот аргумент применяется к файлу или каталогу, на который ссылаются. Чтобы изменить владельца, группу и режим доступа конфигурационного файла, используйте: [.programlisting] .... @sample(games,games,640) etc/config.sample .... Аргументы являются необязательными. Если необходимо изменить только группу и режим, используйте: [.programlisting] .... @sample(,games,660) etc/config.sample .... [WARNING] ==== Если ключевое слово используется в crossref:makefiles[makefile-options,необязательной записи], оно должно быть добавлено после помощника: [.programlisting] .... %%FOO%%@sample etc/orbit.conf.sample .... Это происходит потому, что вспомогательные функции plist для опций используются для закомментирования строки, поэтому они должны быть указаны первыми. Дополнительную информацию см. в crossref:makefiles[options_sub,`OPTIONS_SUB`]. ==== [[plist-keywords-desktop-file-utils]] === `@desktop-file-utils` Будет выполнять `update-desktop-database -q` после установки и удаления. _Никогда_ не используйте напрямую, добавьте crossref:uses[uses-desktop-file-utils,`USES=desktop-file-utils`] в [.filename]#Makefile#. [[plist-keywords-fc]] === `@fc` _каталог_ Добавить запись `@dir` для каталога, переданного в качестве аргумента, и выполнить `fc-cache -fs` для этого каталога после установки и удаления. [[plist-keywords-fontsdir]] === `@fontsdir` _каталог_ Добавить запись `@dir` для каталога, переданного в качестве аргумента, и запустить `mkfontscale` и `mkfontdir` в этом каталоге после установки и удаления. Кроме того, при удалении удаляются кэш-файлы [.filename]#fonts.scale# и [.filename]#fonts.dir#, если они пусты. [[plist-keywords-info]] === `@info` _файл_ Добавляет файл, переданный в качестве аргумента, в plist и обновляет индекс документа info при установке и удалении. Кроме того, удаляет индекс, если он пуст, при удалении. Это никогда не следует использовать вручную, а только через `INFO`. Подробнее см. в crossref:makefiles[makefile-info,Файлы Info]. [[plist-keywords-kld]] === `@kld` _каталог_ Выполняет `kldxref` для каталога при установке и удалении. Дополнительно при удалении каталог будет удалён, если он пуст. [[plist-keywords-rmtry]] === `@rmtry` _файл_ Удаляет файл при удалении и не выдает ошибку, если файл отсутствует. [[plist-keywords-sample]] === `@sample` _файл_ [_файл_] Это используется для обработки установки файлов конфигурации, используя примеры файлов, поставляемых с пакетом. "Реальный" файл (не пример) — это либо второе имя файла, если оно присутствует, либо первое имя файла без расширения [.filename]#.sample#. Это делает три вещи. Во-первых, добавляет первый переданный файл в качестве аргумента, образец файла, в plist. Затем, при установке, если фактический файл не найден, копирует образец файла в фактический файл. И наконец, при удалении, удаляет фактический файл, если он не был изменён. Дополнительную информацию см. в crossref:plist[plist-config, Файлы конфигурации]. [[plist-keywords-shared-mime-info]] === `@shared-mime-info` _каталог_ Выполняет `update-mime-database` для указанного каталога при установке и удалении. [[plist-keywords-shell]] === `@shell` _файл_ Добавить файл, переданный в качестве аргумента, в plist. При установке добавить полный путь к _file_ в [.filename]#/etc/shells#, убедившись, что он не добавлен повторно. При удалении удалите его из [.filename]#/etc/shells#. [[plist-keywords-terminfo]] === `@terminfo` Не использовать самостоятельно. Если порт устанавливает файлы [.filename]#*.terminfo#, добавьте crossref:uses[uses-terminfo,`USES=terminfo`] в его [.filename]#Makefile#. При установке и удалении, если присутствует `tic`, обновить [.filename]#${PREFIX}/shared/misc/terminfo.db# из файлов [.filename]#*.terminfo# в [.filename]#${PREFIX}/shared/misc#. [[plist-keywords-base]] === Основные ключевые слова Есть несколько ключевых слов, которые жёстко закодированы и документированы в man:pkg-create[8]. Для полноты изложения они также документированы здесь. [[plist-keywords-base-empty]] ==== `@` [_файл_] Ключевое слово `empty` является заполнителем, используемым, когда необходимо изменить владельца, группу или права доступа к файлу. Например, чтобы установить группу файла в `games` и добавить бит setgid, добавьте: [.programlisting] .... @(,games,2755) sbin/daemon .... [[plist-keywords-base-exec]] ==== `@preexec` _команда_, `@postexec` _команда_, `@preunexec` _команда_, `@postunexec` _команда_ Выполнить _команду_ как часть процесса установки или удаления пакета. `@preexec` _команда_:: Выполнить _команду_ как часть скриптов [.filename]#pre-install#. `@postexec` _команда_:: Выполнить _команду_ как часть скриптов [.filename]#post-install#. `@preunexec` _команда_:: Выполнить _команду_ как часть скриптов [.filename]#pre-deinstall#. `@postunexec` _команда_:: Выполнить _команду_ как часть скриптов [.filename]#post-deinstall#. Если в _команде_ содержится любая из этих последовательностей, они раскрываются непосредственно. Для следующих примеров предположим, что `@cwd` установлен в [.filename]#/usr/local#, а последним извлечённым файлом был [.filename]#bin/emacs#. `%F`:: Раскрывается до последнего извлеченного имени файла (как указано). В примере [.filename]#bin/emacs#. `%D`:: Раскрыть до текущего префикса каталога, установленного с помощью `@cwd`. В этом примере [.filename]#/usr/local#. `%B`:: Раскрыть до базового имени полного имени файла, то есть префикс текущего каталога плюс последняя спецификация файла, за вычетом имени файла в конце спецификации. В данном примере это будет [.filename]#/usr/local/bin#. `%f`:: Раскрывается до части имени файла в полном квалифицированном имени, или противоположный случай для `%B`. В примере, [.filename]#emacs#. [IMPORTANT] ==== Эти ключевые слова предназначены для помощи в настройке пакета, чтобы он был максимально готов к использованию. Они _не должны_ использоваться для запуска служб, остановки служб или выполнения любых других команд, которые изменяют текущую работающую систему. ==== [[plist-keywords-base-mode]] ==== `@mode` _режим_ Установить разрешения по умолчанию для всех последующих извлекаемых файлов в _режим_. Формат такой же, как используется в man:chmod[1]. Использование без аргумента вернёт разрешения по умолчанию (режим файла при упаковке). [IMPORTANT] ==== Это должен быть числовой режим, например `644`, `4755` или `600`. Нельзя использовать относительный режим, например `u+s`. ==== [[plist-keywords-base-owner]] ==== `@owner` _пользователь_ Установить владельца по умолчанию для всех последующих файлов в _пользователь_. Использование без аргумента вернёт владельца по умолчанию (`root`). [[plist-keywords-base-group]] ==== `@group` _группа_ Установить группу-владельца по умолчанию для всех последующих файлов в _группу_. Использование без аргумента вернёт группу-владельца по умолчанию (`wheel`). [[plist-keywords-base-comment]] ==== `@comment` _строка_ Эта строка игнорируется при упаковке. [[plist-keywords-base-dir]] ==== `@dir` _каталог_ Объявить имя каталога. По умолчанию каталоги, созданные в `PREFIX` при установке пакета, автоматически удаляются. Используйте эту опцию, если необходимо создать пустой каталог в `PREFIX` или если каталогу требуется нестандартный владелец, группа или права. Каталоги за пределами `PREFIX` необходимо регистрировать. Например, [.filename]#/var/db/${PORTNAME}# требует записи `@dir`, тогда как [.filename]#${PREFIX}/shared/${PORTNAME}# — нет, если он содержит файлы или использует стандартные владельца, группу и права. [[plist-keywords-base-exec-deprecated]] ==== `@exec` _команда_, `@unexec` _команда_ (Устарело) Выполнить _команду_ как часть процесса установки или удаления. Рекомендуется использовать crossref:plist[plist-keywords-base-exec, `@preexec` _команда_, `@postexec` _команда_, `@preunexec` _команда_, `@postunexec` _команда_] вместо этого. [[plist-keywords-base-dirrm]] ==== `@dirrm` _каталог_ (Устарело) Объявить имя каталога для удаления при деинсталляции. По умолчанию каталоги, созданные в `PREFIX` при установке пакета, удаляются при его деинсталляции. [[plist-keywords-base-dirrmtry]] ==== `@dirrmtry` _каталог_ (Устарело) Объявить имя каталога для удаления, аналогично `@dirrm`, но не выводить предупреждение, если каталог не может быть удален. [[plist-keywords-creating-new]] === Создание новых ключевых слов Файлы списка пакетов могут быть расширены ключевыми словами, которые определены в каталоге [.filename]#${PORTSDIR}/Keywords#. Настройки каждого ключевого слова хранятся в файле UCL с именем [.filename]#keyword.ucl#. Файл должен содержать как минимум один из следующих разделов: * `attributes` * `action` * `pre-install` * `post-install` * `pre-deinstall` * `post-deinstall` * `pre-upgrade` * `post-upgrade` [[plist-keywords-attributes]] ==== `attributes` Изменяет владельца, группу или режим доступа, используемые ключевым словом. Содержит ассоциативный массив, в котором возможными ключами являются `owner`, `group` и `mode`. Значениями являются, соответственно, имя пользователя, имя группы и режим доступа к файлу. Например: [.programlisting] .... attributes: { owner: "games", group: "games", mode: 0555 } .... [[plist-keywords-action]] ==== `action` Определяет, что происходит с параметром ключевого слова. Содержит массив, где возможные значения: `setprefix`:: Установите префикс для следующих записей в plist. `dir`:: Зарегистрировать каталог для создания при установке и удаления при деинсталляции. `dirrm`:: Зарегистрировать каталог для удаления при деинсталляции. Устарело. `dirrmtry`:: Зарегистрировать каталог для попытки удаления при деинсталляции. Устарело. `file`:: Зарегистрировать файл. `setmode`:: Установить режим для следующих записей plist. `setowner`:: Установить владельца для следующих записей plist. `setgroup`:: Установить группу для следующих записей в plist. `comment`:: Не выполняет никаких действий, эквивалентно отсутствию раздела `action`. `ignore_next`:: Игнорировать следующую запись в plist. [[plist-keywords-arguments]] ==== `arguments` Если установлено значение `true`, добавляется обработка аргументов, разделяя всю строку, `%@`, на нумерованные аргументы, `%1`, `%2`, и так далее. Например, для такой строки: [.programlisting] .... @foo some.content other.content .... `%1` и `%2` будут содержать: [.programlisting] .... some.content other.content .... Это также влияет на работу записи crossref:plist[plist-keywords-action,`action`]. Если аргументов больше одного, необходимо указать номер аргумента. Например: [.programlisting] .... actions: [file(1)] .... [[plist-keywords-pre-post]] ==== `pre-install`, `post-install`, `pre-deinstall`, `post-deinstall`, `pre-upgrade`, `post-upgrade` Эти ключевые слова содержат man:sh[1] скрипт, который выполняется до или после установки, удаления или обновления пакета. В дополнение к обычным заполнителям `@exec %_foo_`, описанным в crossref:plist[plist-keywords-base-exec, `@preexec` _команда_, `@postexec` _команда_, `@preunexec` _команда_, `@postunexec` _команда_], существует новый заполнитель `%@`, который представляет аргумент ключевого слова. [[plist-keywords-examples]] ==== Примеры пользовательских ключевых слов [[plist-keywords-fc-example]] .Пример ключевого слова `@dirrmtryecho` [example] ==== Это ключевое слово выполняет две функции: добавляет строку `@dirrmtry _directory_` в список упаковки и сообщает о том, что каталог удаляется при деинсталляции пакета. [.programlisting] .... actions: [dirrmtry] post-deinstall: <