05 марта 2026 № 1 (2026)

ROSARIUM

газета советского программиста

Стандарт FHS и пути установки

Куда должны попадать файлы программы: бинарники, библиотеки, конфиги, документация.

На этой странице

Одна из задач сборщика — разместить файлы программы в правильных местах. Это определяет стандарт FHS (Filesystem Hierarchy Standard).

Зачем нужен стандарт

Без единого стандарта:

  • Программа A кладёт бинарники в /usr/bin, программа B — в /opt/bin
  • Конфиги в /etc, /usr/etc, ~/.config или в каталоге программы
  • Администратор не знает, где искать логи, данные, настройки

FHS решает эту проблему, определяя назначение каждого каталога.

Основные каталоги FHS

Корневые каталоги

КаталогНазначение
/binОсновные команды (обычно симлинк на /usr/bin)
/sbinСистемные команды (симлинк на /usr/sbin)
/lib, /lib64Библиотеки (симлинки на /usr/lib*)
/etcКонфигурационные файлы
/varИзменяемые данные (логи, кеши, спулы)
/tmpВременные файлы
/homeДомашние каталоги пользователей
/rootДомашний каталог root
/optОпциональные пакеты (обычно проприетарное ПО)

Каталог /usr

Основное место для установки программ:

КаталогНазначениеМакрос RPM
/usr/binИсполняемые файлы пользовательских программ%{_bindir}
/usr/sbinИсполняемые файлы системных программ%{_sbindir}
/usr/lib32-битные библиотеки%{_libdir} (на 32-бит)
/usr/lib6464-битные библиотеки%{_libdir} (на 64-бит)
/usr/libexecВнутренние исполняемые файлы%{_libexecdir}
/usr/includeЗаголовочные файлы C/C++%{_includedir}
/usr/shareАрхитектурно-независимые данные%{_datadir}
/usr/share/manСтраницы руководства man%{_mandir}
/usr/share/infoСтраницы info%{_infodir}
/usr/share/docДокументация%{_docdir}

Каталог /var

Изменяемые данные во время работы:

КаталогНазначение
/var/logЛог-файлы
/var/cacheКешированные данные
/var/libПостоянные данные программ (БД, состояние)
/var/run/runRuntime-данные (PID-файлы, сокеты)
/var/spoolОчереди (почта, печать)
/var/tmpВременные файлы, сохраняемые между перезагрузками

Каталог /etc

Системные конфигурации:

ПутьНазначение
/etc/program.confОсновной конфиг программы
/etc/program.d/Каталог для фрагментов конфигурации
/etc/sysconfig/Параметры запуска служб (в ROSA/Fedora)
/etc/default/Параметры запуска служб (Debian-стиль)

Макросы путей в RPM

В SPEC-файлах всегда используйте макросы вместо жёстко заданных путей:

# Правильно
%{_bindir}/myprogram
%{_libdir}/libmylib.so
%{_datadir}/%{name}/

# Неправильно
/usr/bin/myprogram
/usr/lib64/libmylib.so
/usr/share/myprogram/

Почему макросы важны

  1. Переносимость — на разных системах пути могут отличаться
  2. Мультиархитектурность%{_libdir} автоматически /usr/lib или /usr/lib64
  3. Изменения в будущем — если стандарт изменится, достаточно обновить макросы

Основные макросы

# Посмотреть значения макросов
rpm --eval '%{_bindir}'      # /usr/bin
rpm --eval '%{_libdir}'      # /usr/lib64 (на x86_64)
rpm --eval '%{_datadir}'     # /usr/share
rpm --eval '%{_sysconfdir}'  # /etc
rpm --eval '%{_localstatedir}'  # /var

Полный список:

МакросЗначениеНазначение
%{_prefix}/usrБазовый префикс
%{_exec_prefix}/usrПрефикс для исполняемых файлов
%{_bindir}/usr/binПользовательские программы
%{_sbindir}/usr/sbinСистемные программы
%{_libdir}/usr/lib64Библиотеки (архитектурно-зависимый)
%{_libexecdir}/usr/libexecВспомогательные программы
%{_includedir}/usr/includeЗаголовочные файлы
%{_datadir}/usr/shareДанные (архитектурно-независимые)
%{_mandir}/usr/share/manСтраницы man
%{_infodir}/usr/share/infoСтраницы info
%{_docdir}/usr/share/docДокументация
%{_sysconfdir}/etcКонфигурации
%{_localstatedir}/varИзменяемые данные
%{_rundir}/runRuntime-данные
%{_tmppath}/var/tmpВременные файлы сборки

Правила размещения файлов

Исполняемые файлы

%files
%{_bindir}/myprogram           # Команда для пользователей
%{_sbindir}/myprogram-daemon   # Системная служба
%{_libexecdir}/%{name}/helper  # Внутренний хелпер
Совет
Если программа не предназначена для прямого вызова пользователем — она должна быть в %{_libexecdir}, а не в %{_bindir}.

Библиотеки

%files
%{_libdir}/libmylib.so.1*      # Разделяемая библиотека

%files devel
%{_libdir}/libmylib.so         # Симлинк для линковки
%{_includedir}/mylib.h         # Заголовочный файл
%{_libdir}/pkgconfig/mylib.pc  # pkg-config файл

Данные программы

%files
%{_datadir}/%{name}/           # Данные (иконки, звуки, шаблоны)
%{_datadir}/applications/%{name}.desktop  # Desktop-файл
%{_datadir}/icons/hicolor/*/apps/%{name}.png  # Иконки

Конфигурации

%files
%config(noreplace) %{_sysconfdir}/%{name}.conf
%config(noreplace) %{_sysconfdir}/%{name}.d/*.conf

%config(noreplace) означает: если пользователь изменил файл, при обновлении новая версия будет сохранена как .rpmnew, а изменённая — останется.

Документация

%files
%doc README.md AUTHORS
%license LICENSE COPYING
%{_mandir}/man1/%{name}.1*
%{_infodir}/%{name}.info*

%doc и %license — специальные маркеры, RPM автоматически помещает их в %{_docdir}/%{name}.

Systemd и службы

Для systemd-юнитов:

%files
%{_unitdir}/%{name}.service           # Системная служба
%{_userunitdir}/%{name}.service       # Пользовательская служба
%{_presetdir}/90-%{name}.preset       # Preset-файл
%{_tmpfilesdir}/%{name}.conf          # tmpfiles.d конфиг
%{_sysusersdir}/%{name}.conf          # sysusers.d конфиг

Макросы:

  • %{_unitdir}/usr/lib/systemd/system
  • %{_userunitdir}/usr/lib/systemd/user

Типичные ошибки

Файлы в /usr/local

# Неправильно — /usr/local для ручной установки, не для пакетов
/usr/local/bin/myprogram

Файлы в домашнем каталоге

# Неправильно — пакеты не должны трогать домашние каталоги
/home/user/.config/myprogram/

Жёстко заданный /usr/lib вместо /usr/lib64

# Неправильно — сломается на x86_64
/usr/lib/libmylib.so

# Правильно
%{_libdir}/libmylib.so

Конфиги без %config

# Неправильно — пользовательские изменения будут потеряны
%{_sysconfdir}/%{name}.conf

# Правильно
%config(noreplace) %{_sysconfdir}/%{name}.conf

Практика: анализ пакета

Проанализируйте размещение файлов в существующем пакете:

# Скачать пакет
dnf download htop

# Посмотреть все файлы
rpm -qlp htop-*.rpm

# Проверить соответствие FHS
rpm -qlp htop-*.rpm | while read f; do
  case "$f" in
    /usr/bin/*) echo "BIN: $f" ;;
    /usr/share/man/*) echo "MAN: $f" ;;
    /usr/share/doc/*) echo "DOC: $f" ;;
    /usr/share/*) echo "DATA: $f" ;;
    /etc/*) echo "CONFIG: $f" ;;
    *) echo "OTHER: $f" ;;
  esac
done

Проверьте понимание

  1. Почему в SPEC-файле нужно использовать %{_bindir} вместо /usr/bin?
  2. Куда должна попадать разделяемая библиотека libfoo.so.1.0.0?
  3. Чем отличается %config от %config(noreplace)?
  4. Куда помещать внутренние вспомогательные скрипты программы?
  5. В каком каталоге должны находиться systemd unit-файлы?

Следующий модуль: Анатомия SPEC-файла