Параметры настройки менеджера окон fly-wm#
Важно
Документация дорабатывается по мере развития продуктов Группы Астра и по пожеланиям пользователей.
Ваши пожелания и замечания направляйте на почту docs@astralinux.ru
Общие сведения#
Процесс настройки взаимодействия приложения с пользовательской средой Fly
(менеджер окон fly-wm — менеджер окон, рабочий стол, классическое меню «Пуск», панель инструментов, переключатель рабочих столов, блокировщик экрана),
включает:
создание и регистрацию
*.desktop-файла (ярлыка приложения),создание
*.directory-файла с собственной категорией (для кастомизации ярлыков в меню приложений),настройку ассоциаций MIME-типов (открытие файлов нужным приложением).
Описание функций fly-wmfunc — инструмента редактирования оконного менеджера fly-wm — представлено в статье.
Рабочие каталоги менеджера окон fly-wm (для настройки приложения)#
Системные конфигурационные файлы:
/usr/share/applications/— каталог объектов меню Пуск;/usr/share/fly-wm/shared/flydesktop— размещение в этом каталоге ярлыков (файлов*.desktop), файлов и каталогов приводит к их немедленному появлению на первых рабочих столах всех пользователей (и наоборот, удаление объекта из каталога ведет к удалению объекта с рабочих столов);/usr/share/fly-wm/startmenu— каталог для объектов меню «Пуск» (файлы*.directory— описатель категории меню);/usr/share/fly-wm/shared/flystartmenu— администраторская настройка объектов меню «Пуск» (не рекомендуется использовать);/usr/share/fly-wm/shared/flytoolbar— каталог для объектов панели инструментов (файлы*.desktop);/usr/share/mime/packages/— каталог для XML-файлов регистрации MIME-типов;/usr/share/icons/hicolor— каталог иконок приложения.
Системные файлы применяются ко всем пользователям. Пользовательские настройки, заданные в ~/.fly, имеют приоритет и переопределяют системные.
Примечание
Описанные выше каталоги flydesktop, flystartmenu и flytoolbar задаются переменными окружения FLY_SHARED_DESKTOP_DIR, FLY_SHARED_STARTMENU_DIR, FLY_SHARED_TOOLBAR_DIR.
Директории должны быть созданы заранее (если переменная пустая, то используется каталог по умолчанию из /usr/share/fly-wm/shared/).
Задание значений переменных определяется до запуска службы fly-wm. Это можно сделать, например, при аутентификации пользователя в правилах PAM или создав сценарий в каталоге /etc/X11/Xsession.d/.
После обновления значения переменной необходимо перезапустить сессию.
Нежелательно использовать стандартные пути для нестандартных целей.
Предупреждение
В более ранних обновлениях:
/usr/share/applications/flydesktop— каталог для объектов рабочего стола;/usr/share/applications/flystartmenu— каталог для объектов меню «Пуск»;каталог для объектов панели инструментов отсутствует.
Использование данных каталогов для настройки собственного ПО в последних обновлениях ALSE не рекомендуется.
Конфигурационные файлы#
.desktop-файл — текстовый файл с расширением .desktop, соответствующий стандарту Freedesktop.org.
Он содержит метаданные о приложении и используется для интеграции программы в графические среды рабочего стола Linux.
Основные поля .desktop-файла включают:
название приложения (
Name, поддерживает локализацию черезName[ru]) — обязательное поле,тип объекта (
Type=ApplicationилиType=Links— для ссылок на сайты/документацию, открываются в браузере) — обязательное поле,команда, запускающая приложение (
Exec) — обязательное поле дляType=Application,ссылка (
URL) — обязательное поле дляType=Links,описание (
Comment),рабочая директория, из которой следует запускать команду (
Path),иконка (
Icon),версия (
Version),ключевые слова для поиска из меню (
Keywords),запуск команды из терминала (
Terminal=trueилиTerminal=false),категория (
Categories, например, «Разработка», «Интернет»),список MIME-типов, с которыми может работать приложение (
MimeType).
.directory-файл — это специальный файл, описывающий категорию (или подменю) в меню приложений «Пуск». Он используется для
группировки .desktop-файлов по логическим разделам. Содержит следующие ключевые поля:
Name(отображаемое имя категории, поддерживает локализацию черезName[ru]) — обязательное поле,Categories(имя, по которому*.desktop-файлы ассоциируются с этой категорией),Comment(краткое описание категории, появляется при наведении),Icon(иконка категории),Type=Directory(обязательное поле, указывающее, что это файл категории).
Категория ярлыка — логическая группа, к которой относится программа, связанная с этим ярлыком.
Может использоваться для создания кастомизированной группы в меню Пуск, например, категория «ППО» и входящие в ее состав
«SDK ППО», «Информация о версии ППО», «Лицензия ППО», «Справочник ППО» и др.
Совет
Стандартные категории — Инструменты («Utility»), Научные («Education»), Разработка («Development»), Игры («Game»), Графика («Graphics»), Мобильные («Mobile»), Мультимедиа («Multimedia»), Интернет («Network»), Офис («Office»), Параметры («Settings»), Системные («System»).
MIME (Multipurpose Internet Mail Extensions) — стандарт, описывающий типы файлов (обычно по расширению, определяется
glob-паттерном) и способы их обработки. В контексте Linux-десктопов MIME-типы используются для определения,
какое приложение должно открывать файл определённого типа (в .desktop файле в поле MimeType указываются
MIME-типы, с которыми приложение умеет работать).
MIME-файл содержит описание новых или пользовательских MIME-типов, включая:
<mime-type type="application/x-myformat">— объявление типа,<glob pattern="*.myext"/>— сопоставление файла с MIME-типом (задается glob-паттерном, обычно указывается расширение файла),<comment>— описание типа.
Примечание
Редактор меню Пуск и панели быстрого запуска (fly-menuedit) позволяет графически редактировать ярлыки и категории программ.
Интеграция ППО в ALSE#
Описанные ниже способы настройки рекомендуется использовать в постинсталяционном скрипте.
Предупреждение
Данные настройки актуальны для обновления ALSE 1.8.5.
Предупреждение
Пользовательская настройка имеет приоритет над системной. При возникновении ошибок с системной настройкой рекомендуется проверить нет ли конфликта с пользовательскими настройками.
Добавление приложения в меню Пуск#
Создать
myapp.desktopфайл для приложения myapp:
[Desktop Entry]
Name=My App
Name[ru]=Мое приложение
Exec=/opt/myapp
Icon=myappicon
Type=Application
Categories=Utility;
Terminal=false
Совет
Иконка задается png или svg файлом либо по указанному пути (например, /home/user/myicon.svg), либо ищется сопоставление по имени в каталоге /usr/share/icons/hicolor
(например, если задана ассоциация myappicon с файлом /usr/share/icons/hicolor/scalable/apps/myappicon.svg).
Примечание
Согласно спецификации Freedesktop.org, если в *.desktop указано несколько категорий (например,
«Categories=Office;Utility;»), ярлык добавится только в первую соответствующую категорию (т.е. «Офис»).
Проверить валидность файла:
desktop-file-validate myapp.desktop
Если есть ошибки — будут показаны, если всё хорошо — вывода не будет.
Добавить ярлык в меню (для всех пользователей, требуются права администратора):
sudo mv myapp.desktop /usr/share/applications
Результат — после добавления файла myapp.desktop в директорию /usr/share/applications
иконка приложения автоматически появится у всех пользователей в меню Пуск (появится в пользовательских каталогах ~/.fly/startmenu2 и ~/.fly/startmenu).
Примечание
Удаление файла myapp.desktop из директории /usr/share/fly-wm/startmenu приведет к автоматическому удалению
ярлыка приложения из меню Пуск у всех пользователей.
Совет
Для добавления приложения в меню Пуск от пользователя рекомендуется выполнить графическую настройку из меню
Примечание
При появлении ярлыка приложения в меню Пуск пользователю будет удобно самостоятельно добавить ярлык на рабочий стол, панель инструментов, избранное или автозапуск. Для этого необходимо нажать правой кнопкой мыши на ярлык в меню и нажать кнопку «Добавить».
Создание ярлыка на рабочем столе#
Создать валидный файл myapp.desktop из предыдущего примера в директории /usr/share/fly-wm/shared/flydesktop (для всех пользователей, требуются права администратора).
Результат — после создания файла в директории ярлык автоматически появится на первых
рабочих столах всех пользователей (появится в пользовательском каталоге ~/Desktops/Desktop1).
Примечание
Удаление файла myapp.desktop из директории /usr/share/fly-wm/shared/flydesktop приведет к автоматическому удалению
ярлыка приложения со всех рабочих столов у всех пользователей.
Совет
Для добавления приложения на рабочий стол от пользователя рекомендуется выполнить графическую настройку с рабочего стола: и заполнить обязательные поля «Имя» и «Команда».
Добавление ярлыка на панель инструментов#
Создать
myapp.desktopкак в примере выше.Добавить ярлык на панели инструментов (для всех пользователей, требуются права администратора):
sudo mv myapp.desktop /usr/share/fly-wm/shared/flytoolbar
Результат — файл myapp.desktop появится в каталоге /usr/share/fly-wm/shared/flytoolbar и автоматически появится на
панели инструментов всех пользователей (появится в пользовательском каталоге ~/.fly/toolbar/).
Примечание
Удаление файла myapp.desktop из директории /usr/share/fly-wm/shared/flytoolbar приведет к автоматическому удалению
ярлыка приложения с панели инструментов у всех пользователей.
Совет
Для добавления приложения на панель управления пользователю необходимо выполнить следующие действия: .
Задание иконки#
Иконка задается файлами png или svg, который необходимо поместить в соответствующую директорию
(для png файла — /usr/share/icons/hicolor/<размер>/apps/имя_иконки.png, для svg — /usr/share/icons/hicolor/scalable/apps/имя_иконки.svg):
sudo mv myicon.png /usr/share/icons/hicolor/48x48/apps/myicon.png
Совет
Рекомендуется использовать несколько размеров (16x16, 32x32, 48x48, 64x64, 128x128), но достаточно хотя бы одного — система подберёт ближайший.
Результат — иконка появится в реестре иконок и может быть использована по имени как значок ярлыка.
Настройка ассоциации MIME-типа#
До настройки ассоциации (связи *.xml с *.desktop) необходимо убедиться, что *.desktop имеет поле MimeType и находится в ~/.fly/startmenu или ~/.fly/startmenu2
(пользовательские приложения) или /usr/share/applications/ (стандартные приложения Astra Linux Special Edition).
Пусть задан файл myapp.desktop:
[Desktop Entry]
Name=My app
Name[ru]=Мое приложение
Exec=/usr/bin/myapp
Icon=myapplication
Type=Application
Categories=Utility;
Terminal=false
MimeType=application/x-myapp;
Предупреждение
Согласно Freedesktop.org Desktop Entry Specification,
поле MimeType должно содержать полные имена MIME-типов в формате type/subtype, где type может быть
application, text, video или image, а subtype — x-myapp, pdf, png или др. Использование неправильных типов может приводить к ошибкам связывания.
1. Для работы приложения с определёнными файлами (например, *.myapp) необходимо зарегистрировать MIME-тип в системе,
создав файл application-x-myapp.xml:
<?xml version="1.0" encoding="UTF-8"?>
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
<mime-type type="application/x-myapp">
<comment>MyApp Data File</comment>
<glob pattern="*.myapp"/> <!-- glob-паттерн для файлов, например, config_*.cfg -->
</mime-type>
</mime-info>
Установить новый MIME-тип в системе (требуются права администратора):
sudo mv application-x-myapp.xml /usr/share/mime/packages/
sudo update-mime-database /usr/share/mime
Связать его с приложением:
# Задание однозначного выбора для открытия файлов приложением (если не задано, будет предлагаться список подходящих приложений, работающих с данным mime-типом)
xdg-mime default myapp.desktop application/x-myapp
Результат — описанные в mime файлы (заданные glob-паттерном, например, .myapp) открываются системой в заданном
приложении. Проверить работоспособность можно, открыв файл new.myapp командой xdg-open new.myapp.
Создание новой категории#
1. Создать папку MyApp с описателем категории .directory (обязательные поля - Type=Directory, Name, Categories)
следующего содержания:
Совет
Иконка (icon) должна быть задана предварительно, если используется нестандартная. В примере folder - стандартная иконка каталогов.
[Desktop Entry]
Name=MyApp Tools
Name[ru]=Средства MyApp
Icon=folder
Type=Directory
Categories=X-MyCategoryName
Скопировать каталог
MyApp, содержащий описатель.directory, в/usr/share/fly-wm/startmenu(содержат описание нестандартных категорий меню):
sudo mv MyApp /usr/share/fly-wm/startmenu
Примечание
Новая категория появится в меню Пуск у всех пользователей.
3. Создать файл MyApp.desktop с новой категорией и добавить его в меню Пуск (если *.desktop с новой категорией был
создан до выполнения шагов 1-2, он находился в категории меню «Прочее», а после создания новой категории меню переместится в нее).
[Desktop Entry]
Name=MyApp
Name[ru]=MyApp
Exec=/usr/bin/myapp
Icon=myapp
Terminal=false
Type=Application
Categories=X-MyCategoryName;
Совет
Согласно спецификации Freedesktop.org, собственная категория должна начинаться с префикса «X-«.
Примечание
В новой категории меню Пуск у всех пользователей появится ярлык приложения.
Результат — ярлыки приложений (*.desktop) с заданной категорией X-MyCategoryName отобразятся в меню «Пуск»
в новой категории меню.
Предупреждение
Изменение категории в файле *.desktop, уже находящегося в каталоге /usr/share/fly-wm/startmenu/,
не приведет к перемещению ярлыка приложения в новую категорию меню (даже после ручного обновления оконного менеджера с помощью fly-wmfunc).
Обновление оконного менеджера#
При изменении файлов в /usr/share/ системным администратором обновление происходит
автоматически. Ниже приведены команды fly-wmfunc, с помощью которых можно применить изменения вручную.
Принудительное обновление стартового меню (применение - после добавления новой категории, добавление MimeType):
fly-wmfunc FLYWM_CREATE_STARTMENU
Предупреждение
Изменение полей Name, Exec, Icon, Comment, MimeType (требуется также перезадание с помощью xdg-mime),
Path, Terminal, Version, Keywords в файле *.desktop приведёт к автоматическому изменению ярлыка.
Изменение поля Type может сломать ярлык. Изменение поля Categories в уже установленном файле не перемещает ярлык в меню.
Переименование файла *.desktop может сломать системные ассоциации.
Обновление значков на рабочем столе:
fly-wmfunc FLYWM_UPDATE_SHORTCUT
Совет
Принудительное обновление FLYWM_FORCE_UPDATE_SHORTCUT.
Обновление панели быстрого запуска:
fly-wmfunc FLYWM_UPDATE_TOOLBAR
Перезагрузка графической сессии пользователя без перезагрузки сессии:
fly-wmfunc FLYWM_RESTART
Предупреждение
Не выполнять в скриптах deb пакета.
Перезапуск меню у всех пользователей:
sudo killall fly-start-menu
Предупреждение
Изменение в файлах каталога /usr/share/fly-wm может не привести к изменению даже после выполнения команд выше.
Рабочим вариантом является удаление изменяемого файла и последующее его создание с изменениями.
Настройка простого Python-приложения#
Рекомендуемая структура deb-пакета проприетарного ПО:
app-package/
├── debian/ # Метаданные пакета (Содержимое представлено в тексте ниже)
├── opt/
│ └── app/ # Все файлы приложения (распаковывается в /opt/app/)
│ ├── script # Файл приложения (исходники/код)
│ └── lib/ # Библиотеки
├── integration/ # Интеграционные файлы
│ ├── application-x-app.xml # Задание MIME-тип (распаковывается в /usr/share/mime/packages/)
│ ├── app -> /opt/app/script # Симлинк/скрипт-обертка для запуска из терминала (распаковывается в /usr/bin/)
│ ├── app.desktop # Ярлык для меню/рабочего стола/панели инструментов (распаковывается в /usr/share/applications/ и папки flydesktop, flytoolbar каталога в /usr/share/fly-wm/shared/)
│ ├── app.svg или app.png # Иконка для ярлыка/категории (распаковываются в /usr/share/icons/hicolor/)
│ └── AppCategory/
│ └── .directory # Новая категория меню (распаковывается в /usr/share/fly-wm/startmenu)
└── config.conf # Конфигурационный файл приложения (распаковывается в /etc/app/, помечается как conffile при remove, удаляются при purge)
Ниже представлены шаги создания deb-пакета приложения с интеграцией в Astra Linux Special Edition.
Создание приложения#
Приложение myapp будет открывать файлы *.myapp и показывать их Содержимое.
Установить
python3иpyqt5:
sudo apt install python3 python3-pyqt5
Создать рабочую директорию
myapp-1.0и дерево папок с файлами (Содержимое файлов будет представлено ниже):
myapp-1.0/
├── opt/ # Каталог пользовательских приложений
│ └── myapp/ # Каталог приложения
│ ├── myapp.py # Скрипт приложения
│ └── file.myapp # Файл открываемый приложением
└── integration/ # Интеграционные файлы
├── application-x-myapp.xml # Задание MIME-тип
├── cat_myapp.svg # Иконка категории меню (опционально)
├── myapp # Скрипт-обертка для запуска из терминала
├── myapp.png # Иконка ярлыка приложения (опционально)
├── myapp.desktop # Ярлык приложения для меню
├── myapp-desktop.desktop # Ярлык приложения для рабочего стола (копия)
├── myapp-toolbar.desktop # Ярлык приложения для панели инструментов (копия)
└── MyAppCategory/.directory # Категория меню
Содержимое файла
myapp-1.0/opt/myapp/myapp.py:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
MyApp - PyQt5 приложение для демонстрации интеграции в ALSE/Fly-WM
"""
import sys
import os
from PyQt5.QtWidgets import (
QApplication,
QMainWindow,
QWidget,
QVBoxLayout,
QLabel,
QTextEdit,
QMessageBox
)
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QFont
class MyAppWindow(QMainWindow):
def __init__(self, filepath=None):
super().__init__()
self.filepath = filepath
self.init_ui()
# Если файл передан при запуске - открываем его
if filepath:
self.open_file(filepath)
def init_ui(self):
"""Инициализация интерфейса"""
self.setWindowTitle("MyApp")
self.setGeometry(100, 100, 600, 400)
# Центральный виджет
central_widget = QWidget()
self.setCentralWidget(central_widget)
# Основной layout
layout = QVBoxLayout()
central_widget.setLayout(layout)
# Заголовок
self.title_label = QLabel("Добро пожаловать в MyApp!")
self.title_label.setFont(QFont("Arial", 14, QFont.Bold))
self.title_label.setAlignment(Qt.AlignCenter)
layout.addWidget(self.title_label)
# Текстовая область
self.text_area = QTextEdit()
self.text_area.setFont(QFont("Arial", 10))
self.text_area.setReadOnly(True) # Только для чтения
self.text_area.setLineWrapMode(QTextEdit.WidgetWidth)
layout.addWidget(self.text_area)
# Приветственный текст
welcome_text = (
"Это приложение запущено из меню.\n\n"
"Оно работает с файлами *.myapp и служит шаблоном для интеграции в ALSE.\n"
"Для тестирования откройте файл file.myapp из меню двойным кликом."
)
self.text_area.setPlainText(welcome_text)
def open_file(self, filepath):
"""Открытие файла"""
try:
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
self.text_area.setPlainText(content)
self.setWindowTitle(f"MyApp - {os.path.basename(filepath)}")
self.title_label.setText(f"Открыт файл: {filepath}")
except Exception as e:
self.text_area.setPlainText(f"Ошибка при открытии файла:\n{str(e)}")
self.title_label.setText("Ошибка открытия файла")
QMessageBox.critical(self, "Ошибка", f"Не удалось открыть файл:\n{str(e)}")
def main():
# Создание приложения
app = QApplication(sys.argv)
# Получение пути к файлу из аргументов командной строки
filepath = sys.argv[1] if len(sys.argv) > 1 else None
# Создание и показ окна
window = MyAppWindow(filepath)
window.show()
# Запуск цикла событий
sys.exit(app.exec_())
if __name__ == "__main__":
main()
Сделать приложение исполняемым:
sudo chmod +x myapp-1.0/opt/myapp/myapp.py
Файл для тестирования
myapp-1.0/opt/myapp/file.myapp:
Test string in file.
6. Сделать скрипт-обертку myapp-1.0/integration/myapp для запуска приложения из терминала
(предпочтительнее симлинка, т.к. позволяет менять версию Python или добавлять переменные окружения
без изменения основного скрипта приложения):
#!/bin/sh
exec /opt/my-company/myapp/myapp.py "$@"
Содержимое файлов
myapp-1.0/integration/myapp.desktop,myapp-1.0/integration/myapp-desktop.desktop,myapp-1.0/integration/myapp-toolbar.desktop:
[Desktop Entry]
Version=1.0
Type=Application
Name=MyApp
Name[ru]=Моё приложение
Comment=Просмотр .myapp файлов
Exec=/opt/my-company/myapp/myapp.py %f
# Альтернатива: Exec=/usr/bin/myapp %f
Icon=myapp
Terminal=false
Categories=X-MyAppCategory;
MimeType=application/x-myapp;
Содержимое файла
myapp-1.0/integration/MyAppCategory/.directory:
[Desktop Entry]
Name=MyApp Tools
Name[ru]=Инструменты MyApp
Comment=Приложения MyApp
Icon=cat_myapp
Type=Directory
Categories=X-MyAppCategory;
Совет
Для корректной отработки проверки *.desktop файла категория должна начинаться с префикса X-.
Регистрация MIME-типа в файле
myapp-1.0/integration/application-x-myapp.xml:
<?xml version="1.0" encoding="UTF-8"?>
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
<mime-type type="application/x-myapp">
<comment>MyApp Data File</comment>
<glob pattern="*.myapp"/>
<icon name="myapp"/>
</mime-type>
</mime-info>
Добавить файлы иконок по путям
myapp-1.0/integration/myapp.svgиmyapp-1.0/integration/myapp.png.Перейти в каталог
myapp-1.0и инициализировать файлы упаковки (в папкеdeb):
cd myapp-1.0
dh_make -n --createorig -p myapp -e test@email.com
Редактировать Содержимое папки debian, оставив следующую структуру:
debian/ # Файлы упаковки пакета
├── source/
│ └── format # Формат исходного пакета (3.0 native или 3.0 quilt)
├── changelog # История версий, версия пакета, контакты сопровождающего
├── control # Метаданные пакета: зависимости, описание, секция
├── copyright # Лицензионная информация и авторские права (текстовый файл)
├── myapp.install # Список файлов для установки
├── postinst # Скрипт, выполняемый после установки
├── postrm # Скрипт, выполняемый после удаления
├── prerm # Скрипт, выполняемый до удаления
└── rules # Скрипт сборки (Makefile), управляющий процессом компиляции и упаковки
Примечание
Шаблонные пользовательские конфигурационные файлы могут задаваться с помощью debian/conffiles,
в котором записываются абсолютные пути пользовательских конфигурационных файлов (для БД, приложения и т.д.).
Важно, deb-пакет должен содержать перечисленные файлы, правила распаковки которых должны быть заданы в „.install“.
Пример содержания debian/conffiles:
/opt/my-company/myapp/config/app.conf
/opt/my-company/myapp/config/database.ini
/etc/my-company/myapp/myapp.conf
Содержимое файла
source/format:
3.0 (native)
Содержимое файла
changelog:
myapp (1.0-1) unstable; urgency=medium
* Initial release
* Integration with ALSE/Fly-WM
* Support for .myapp file format
-- Test Name <test@mail.ru> Thu, 24 Mar 2026 15:00:00 +0300
Содержимое файла
control:
Source: myapp
Section: utils
Priority: optional
Maintainer: Test <test@email.com>
Build-Depends: debhelper-compat (= 13), desktop-file-utils, python3, python3-pyqt5, xdg-utils
Standards-Version: 4.5.0
Rules-Requires-Root: no
Package: myapp
Architecture: all
Depends: python3, python3-pyqt5, xdg-utils, ${misc:Depends}
Recommends: x11-utils, dbus-x11, fly-wm
Suggests: desktop-file-utils
Breaks: myapp-old (<< 1.0)
Replaces: myapp-old (<< 1.0)
Section: utils
Priority: optional
Description: Демо-приложение для интеграции в ALSE
Это приложение служит шаблоном для создания .deb-пакетов для ALSE 1.8 (на базе Debian 12).
Особенности:
- Установка в /opt/my-company/myapp
- Ярлык в меню Пуск
- Поддержка открытия файлов *.myapp
- Интеграция с Fly-WM (меню, рабочий стол, панель инструментов)
Содержимое файла
copyright:
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: myapp
Upstream-Contact: Test Name <test@email.com>
Source: https://your-repo.com/myapp
Files: *
Copyright: 2025 Test Name
License: MIT
Содержимое файла
myapp.install:
# Приложение (копируется вся папка) - рекомендуется структура /opt/<vendor>/<package>/ для мультипакетных вендоров
opt/myapp /opt/my-company/
# Скрипт-обертка
integration/myapp /usr/bin/my-company/
# Интеграция Fly-WM (меню Пуск, рабочий стол, панель инструментов)
integration/myapp.desktop /usr/share/applications/
integration/MyAppCategory /usr/share/fly-wm/startmenu/
integration/myapp-desktop.desktop /usr/share/fly-wm/shared/flydesktop/
integration/myapp-toolbar.desktop /usr/share/fly-wm/shared/flytoolbar/
# MIME-типы
integration/application-x-myapp.xml /usr/share/mime/packages/
# Иконки
integration/cat_myapp.svg /usr/share/icons/hicolor/scalable/apps/
integration/myapp.png /usr/share/icons/hicolor/48x48/apps/
Содержимое файла
postinst:
#!/bin/bash
# debian/postinst
# Вызывается dpkg после установки пакета.
PACKAGE="myapp"
xdg-mime default "${PACKAGE}.desktop" "application/x-${PACKAGE}"
#DEBHELPER#
exit 0
При вызове команды установки пакета скрипт postinst вызывается пакетным менеджером dpkg
после размещения файлов пакета в системе. В данном скрипте выполняется базовая подготовка
окружения: финальное обновление системных кэшей (с помощью #DEBHELPER#) и регистрация ассоциаций файлов.
Совет
Файлы, ассоциированные для открытия установленным приложением, будут создаваться с ярлыком приложения.
Для уже созданных файлов ярлыки в проводнике обновятся после перезапуска менеджера файлов в активной сессии.
На рабочем столе ярлыки файлов обновятся после выполнения команды fly-wmfunc FLYWM_FORCE_UPDATE_SHORTCUT.
Описанные выше две настройки применятся сразу для уже созданных файлов при перезагрузке сессии пользователя (или выполнении команды fly-wmfunc FLYWM_RESTART).
Содержимое файла
postrm:
#!/bin/bash
# debian/postrm
# Вызывается dpkg после удаления пакета.
ACTION="${1:-}"
case "$ACTION" in
purge)
[ -d /opt/my-company/myapp ] && rm -rf /opt/my-company/myapp 2>/dev/null || true
;;
esac
fly-wmfunc FLYWM_FORCE_UPDATE_SHORTCUT
#DEBHELPER#
exit 0
При вызове команды удаления пакета скрипт postrm вызывается пакетным менеджером dpkg после удаления
отслеживаемых файлов пакета (перечисленных в myapp.install и debian/conffiles). При этом пакетный менеджер самостоятельно работает с
конфигурационными файлами (conffiles): в сценарии remove они сохраняются в системе, а в сценарии purge — удаляются.
После завершения этих операций запускается скрипт postrm:
В сценарии
removeпеременнаяACTIONравнаremove. Блокcaseне срабатывает, управление сразу переходит к#DEBHELPER#, который обновляет системные кэши (иконки, MIME, desktop) и завершает работу скрипта.В сценарии
purgeпеременнаяACTIONравнаpurge. Выполняется принудительная очистка каталога/opt/my-company/myappдля удаления runtime-данных, кэша и логов, созданных приложением. После этого отрабатывает#DEBHELPER#и скрипт завершается.
Совет
Если
/opt/my-company/myappсодержит только файлы, установленные пакетом (через debian/install), тоdpkgудалит их сам до запуска postrm. В postrm эта папка уже будет пустой или удаленной.Если
/opt/my-company/myappсодержит данные, созданные пользователем во время работы программы (логи, кэш, базы данных), которые не входят в состав пакета, тогда при remove не будут удалены пользовательские данные из/opt/my-company/myapp, при purge будет удален весь каталог/opt/my-company/myapp.
Содержимое файла
prerm:
#!/bin/bash
# debian/prerm
# -*- coding: utf-8 -*-
# Вызывается dpkg перед удалением файлов пакета.
ACTION="$1"
PACKAGE="myapp"
echo "🛑 $PACKAGE prerm: Запуск действия '$ACTION'..."
terminate_processes() {
# Ищем только точное совпадение с запуском python3
local pids
pids=$(pgrep -f "${PACKAGE}\.py" 2>/dev/null || true)
[ -z "$pids" ] && { echo "ℹ️ Запущенных экземпляров ${PACKAGE} не обнаружено."; return 0; }
echo "⚠️ SIGTERM для PID: $pids"
kill -TERM $pids 2>/dev/null || true
# Ждём до 3 секунд, проверяем каждую секунду
for i in 1 2 3; do
local alive=0
for pid in $pids; do
kill -0 "$pid" 2>/dev/null && alive=1
done
[ $alive -eq 0 ] && break
sleep 1
done
# Если что-то зависло — добиваем
if kill -0 $pids 2>/dev/null; then
echo "⚠️ SIGKILL для неотвечающих PID: $pids"
kill -KILL $pids 2>/dev/null || true
fi
}
case "$ACTION" in
upgrade|remove|purge|failed-upgrade|abort-install|abort-upgrade)
terminate_processes
;;
*)
echo "ℹ️ Действие '$ACTION' не требует предварительной остановки процессов."
;;
esac
exit 0
Если приложение работает как сервис
Скрипт prerm (systemd сам реализует: SIGTERM → 90s timeout → SIGKILL):
#!/bin/bash
PACKAGE="myapp"
set -e
if [ "$1" = "remove" ] || [ "$1" = "upgrade" ]; then
systemctl stop "${PACKAGE}.service" 2>/dev/null || true
fi
Содержимое файла
rules:
#!/usr/bin/make -f
%:
dh $@
Скрипт rules для отладки
#!/usr/bin/make -f
# Включить verbose-режим для отладки
export DH_VERBOSE=1
PACKAGE=myapp
%:
dh $@
# -----------------------------------------------------------------------------
# Проверка скриптов сопровождения (выполняется после dh_installdeb)
# -----------------------------------------------------------------------------
execute_after_dh_installdeb:
@echo "🔍 Проверка скриптов сопровождения..."
@echo "=========================================="
@for script in postinst preinst postrm prerm; do \
if [ -f debian/$$script ]; then \
echo "✅ Проверка: $$script"; \
\
# 1. Проверка исполняемости \
if [ ! -x debian/$$script ]; then \
echo "❌ ОШИБКА: $$script не исполняемый!"; \
echo " Выполните: chmod +x debian/$$script"; \
exit 1; \
fi; \
echo " ✓ Исполняемый"; \
\
# 2. Проверка синтаксиса bash \
if ! bash -n debian/$$script 2>/dev/null; then \
echo "❌ ОШИБКА: $$script имеет синтаксические ошибки!"; \
bash -n debian/$$script; \
exit 1; \
fi; \
echo " ✓ Синтаксис верен"; \
\
# 3. Проверка shebang \
if ! head -1 debian/$$script | grep -q "^#!/bin/\(ba\|da\)sh"; then \
echo "⚠️ ПРЕДУПРЕЖДЕНИЕ: $$script имеет нестандартный shebang"; \
fi; \
echo " ✓ Shebang корректен"; \
\
# 4. Проверка наличия exit 0 в конце \
if ! tail -5 debian/$$script | grep -q "exit 0"; then \
echo "⚠️ ПРЕДУПРЕЖДЕНИЕ: $$script может не иметь 'exit 0' в конце"; \
else \
echo " ✓ exit 0 присутствует"; \
fi; \
\
# 5. Проверка #DEBHELPER# (для postinst/postrm/prerm) \
if [ "$$script" != "preinst" ]; then \
if grep -q "^#DEBHELPER#$$" debian/$$script; then \
echo " ✓ #DEBHELPER# найден"; \
else \
echo "⚠️ ПРЕДУПРЕЖДЕНИЕ: #DEBHELPER# не найден (не критично)"; \
fi; \
fi; \
\
# 6. Проверка на опасный set -e в скриптах удаления \
if [ "$$script" = "postrm" ] || [ "$$script" = "prerm" ]; then \
if head -10 debian/$$script | grep -q "^set -e"; then \
echo "⚠️ ПРЕДУПРЕЖДЕНИЕ: set -e в $$script может прервать удаление!"; \
echo " Рекомендуется убрать set -e или добавить '|| true'"; \
else \
echo " ✓ set -e не обнаружен (безопасно)"; \
fi; \
fi; \
\
echo ""; \
else \
echo "ℹ️ $$script отсутствует (не критично)"; \
fi; \
done
@echo "=========================================="
@echo "✅ Все проверки скриптов завершены"
@echo ""
# -----------------------------------------------------------------------------
# Дополнительная проверка .desktop файлов (если есть)
# -----------------------------------------------------------------------------
execute_after_dh_install:
@echo "🔍 Проверка .desktop файлов..."
@if find debian/$(PACKAGE) -name "*.desktop" -type f 2>/dev/null | grep -q .; then \
for file in $$(find debian/$(PACKAGE) -name "*.desktop" -type f); do \
echo " Проверка: $$file"; \
if command -v desktop-file-validate >/dev/null 2>&1; then \
if ! desktop-file-validate "$$file" 2>/dev/null; then \
echo "❌ ОШИБКА: $$file не прошёл валидацию!"; \
desktop-file-validate "$$file"; \
exit 1; \
fi; \
echo " ✓ Валидация пройдена"; \
else \
echo " ⚠️ desktop-file-validate не установлен (пропуск)"; \
fi; \
done; \
else \
echo " ℹ️ .desktop файлы не найдены"; \
fi
@echo ""
# -----------------------------------------------------------------------------
# Проверка файла debian/install
# -----------------------------------------------------------------------------
execute_before_dh_install:
@echo "🔍 Проверка debian/install..."
@if [ -f debian/$(PACKAGE).install ]; then \
echo " ✓ Файл install существует"; \
while read -r src dst; do \
case "$$src" in \
\#*|"") continue ;; \
esac; \
if [ ! -e "$$src" ]; then \
echo "❌ ОШИБКА: Файл '$$src' не найден!"; \
exit 1; \
fi; \
echo " ✓ Найден: $$src → $$dst"; \
done < debian/$(PACKAGE).install; \
else \
echo " ℹ️ debian/$(PACKAGE).install не найден"; \
fi
@echo ""
Сделать скрипты исполняемыми:
chmod +x postinst
chmod +x prerm
chmod +x postrm
chmod +x rules
Собрать пакет, перейдя в
myapp-1.0:
# Сборка пакета
dpkg-buildpackage -us -uc -b
# Установка пакета
sudo dpkg -i myapp*.deb
# Удаление пакета (с сохранением логов и конфигов)
sudo dpkg -r myapp
# Полное удаление пакета
sudo dpkg -P myapp
Примечание
После установки пакета ярлыки приложения автоматически появятся в меню «Пуск», на рабочем столе и панели инструментов, а в файловом менеджере обновятся иконки ассоциированных файлов.
Проверка корректности remove
Файл-скрипт проверки:
#!/bin/bash
PACKAGE="myapp"
OPT_DIR="/opt/my-company/${PACKAGE}"
BIN="/usr/bin/${PACKAGE}"
echo "=========================================="
echo "🔍 Проверка состояния после 'dpkg -r ${PACKAGE}'"
echo "=========================================="
# 1. Статус пакета в реестре
STATUS=$(dpkg-query -W -f='${db:Status-Abbrev}' "${PACKAGE}" 2>/dev/null)
case "$STATUS" in
rc)
echo "✅ Статус: rc (удалён, конфиги сохранены) — КОРРЕКТНО для 'dpkg -r'"
;;
ii)
echo "❌ Статус: ii (пакет установлен) — УДАЛЕНИЕ НЕ ПРОИЗОШЛО"
;;
*)
echo "⚠️ Статус: '${STATUS:-отсутствует}' (ожидается 'rc')"
;;
esac
# 2. Удаление отслеживаемых файлов пакета
TRACKED_FILES_REMOVED=true
if [ -e "${OPT_DIR}/${PACKAGE}.py" ]; then echo "❌ Файл пакета остался: ${OPT_DIR}/${PACKAGE}.py"; TRACKED_FILES_REMOVED=false; fi
if [ -e "${BIN}" ]; then echo "❌ Файл/ссылка пакета осталась: ${BIN}"; TRACKED_FILES_REMOVED=false; fi
if [ "$TRACKED_FILES_REMOVED" = true ]; then
echo "✅ Все отслеживаемые файлы пакета удалены"
fi
# 3. Сохранение пользовательских конфигов (нормально для remove)
if [ -d "${OPT_DIR}/config" ] || find "${OPT_DIR}" \( -name "*.conf" -o -name "*.ini" \) 2>/dev/null | grep -q .; then
echo "✅ Конфигурационные файлы сохранены (штатное поведение remove)"
else
echo "ℹ️ Конфигурационные файлы не обнаружены (возможно, их не было в пакете)"
fi
# 4. Метаданные dpkg (должны остаться!)
INFO_COUNT=$(ls -1 /var/lib/dpkg/info/"${PACKAGE}".* 2>/dev/null | wc -l)
if [ "$INFO_COUNT" -gt 0 ]; then
echo "✅ Метаданные в /var/lib/dpkg/info/ сохранены ($INFO_COUNT файлов) — КОРРЕКТНО"
else
echo "⚠️ Метаданные отсутствуют (неожиданно для 'dpkg -r', возможно был purge)"
fi
# 5. Процессы приложения
PIDS=$(pgrep -f "^python3 .*${PACKAGE}\.py" 2>/dev/null || true)
if [ -z "$PIDS" ]; then
echo "✅ Процессы приложения завершены"
else
echo "❌ Обнаружены запущенные процессы: $PIDS"
fi
# 6. Целостность базы пакетов
if dpkg --audit 2>/dev/null | grep -q "^${PACKAGE}"; then
echo "❌ dpkg --audit сообщает о проблемах с пакетом"
else
echo "✅ База dpkg консистентна (audit чист)"
fi
echo "=========================================="
Руководство по устранению неполадок (Troubleshooting Guide)
Восстановление после сбоев установки/удаления
Если при установке или удалении пакета произошли критические ошибки, перед повторной попыткой необходимо убедиться, что система находится в консистентном состоянии.
1. Стандартные средства восстановления
Штатные команды dpkg и apt:
sudo dpkg --configure -a
sudo apt --fix-broken install
Если эти команды завершились успешно, повторная установка должна пройти нормально.
2. Принудительная очистка (если п.1 не помог)
Если пакет «завис» в состоянии half-installed или half-configured:
# Проверка статуса
dpkg -l | grep myapp
# Если пакет виден — попробовать принудительное удаление
sudo dpkg --purge --force-all myapp
3. Ручная очистка
Используйте этот метод только если предыдущие шаги не сработали. Внимание: Неправильное редактирование базы dpkg может сделать систему неработоспособной!
# 1. Создайте резервную копию статуса!
sudo cp /var/lib/dpkg/status /var/lib/dpkg/status.backup
# 2. Проверьте, осталась ли запись о пакете
if dpkg -l | grep -q "^.. myapp "; then
echo "⚠️ Запись о пакете найдена. Удаляем вручную..."
# Удаляем блок, начинающийся с "Package: myapp" до следующей пустой строки или следующего "Package:"
sudo sed -i '/^Package: myapp$/,/^\(Package:\|$\)/{ /^Package: myapp$/!{/^Package:/!d;};}' /var/lib/dpkg/status
# Более безопасный вариант — использовать dpkg-remove-obsolete или dpkg --remove --force-remove-reinstreq
fi
# 3. Удалите файлы информации о пакете
sudo rm -f /var/lib/dpkg/info/myapp.*
# 4. Обновите кеш зависимостей
sudo apt update
Проверка системы
После выполнения процедур убедитесь, что следов пакета не осталось:
# Проверка реестра
dpkg -l | grep myapp && echo "❌ Остались записи" || echo "✅ Реестр чист"
# Проверка файлов информации
[ $(find /var/lib/dpkg/info -name 'myapp.*' 2>/dev/null | wc -l) -eq 0 ] && echo "✅ Файлы info удалены" || echo "❌ Файлы info остались"
# Проверка установленных файлов (опционально)
[ ! -d /opt/my-company/myapp ] && echo "✅ Приложение удалено" || echo "❌ Каталог приложения остался"
Только после прохождения всех проверок можно повторно устанавливать исправленный пакет.
Полезные ссылки:
Совет
Достаточным является добавление приложения в меню Пуск, т.к. из него удобно добавлять приложение на рабочий стол,
в панель инструментов и автозапуск. Если в myapp.install файл myapp.desktop размещать в
каталоге /usr/share/fly-wm/shared/flydesktop, то после распаковки ярлык приложения появится
на рабочем столе всех пользователей. Если в myapp.install файл myapp.desktop размещать в
каталоге /usr/share/fly-wm/shared/flytoolbar, то после распаковки ярлык приложения появится
на панели инструментов всех пользователей.