В любой игре, если только она не вечная MMORPG, вы рано или поздно встретите финального босса и закончите игру с победой. Увлекательный квест с инструментом упаковки snapcraft вам не гарантирует, что уровень ваших познаний позволит запихать программу в самодостаточный пакет snap. Но чувство когда удалось победить все проблемы и оформить для людей программу, которая никогда не была легко доступна пользователям, не просто передать и описа́ть.
Представьте что программа - это буйный пациент, а вы - медбрат, которого доктор попросил надеть смирительную рубашку на больного. Больной брыкается и цепляется своими ручонками за всё что не попадя. Нужно аккуратно отцепить пациента от окружающего мира и нежно спеленать его аки куколку.
Более подробно как паковать программы в snap будет разжёвано в поздних статьях на примере GTK программы DeaDBeeF. Упаковка там сложнее в том плане, что программа собирается из исходников, юзает графический тулкит GTK, который цепляет +100500 компонентов. Искренне хотел, чтобы автор проекта сам выставлял проект в Ubuntu Store. Поделился с ним наработками и дал время, но, не зная окончательного решения upstream, не удержался и выложил программу сам под именем deadbeef-vs.
Сегодня опять Java программа и базовые приёмы при упаковке софта в snap. Нам нужен пустой каталог и в нём создаётся пустой файл snapcraft.yaml. Пишем в нём базовые поля: name, version, summary, description, confinement, architectures.
На примере Oracle SQL Developer Data Modeler.
name: osddm version: "4.1.3.901-snap1" summary: Oracle SQL Developer Data Modeler description: | Oracle SQL Developer Data Modeler is a free graphical tool that enhances productivity and simplifies data modeling tasks. Using Oracle SQL Developer Data Modeler users can create, browse and edit, logical, relational, physical, multi-dimensional, and data type models. The Data Modeler provides forward and reverse engineering capabilities and supports collaborative development through integrated source code control. The Data Modeler can be used in both traditional and in Cloud environments. confinement: strict architectures: [amd64]
Поля имеют самоговорящие названия, но позволю их ещё разжевать:
snap list|find
sudo snap install --devmode app-version.snap
. Если вы не справитесь до конца и программа в строгом режиме strict не работает, то в режиме devmode snap пакет можно залить в Ubuntu Store только для каналов beta и edge. То есть простой пользователь не увидит ваше детище через stable канал и не сможет легко установить программу через GNOME Software. В консоли пользователю придётся писать sudo snap install your-snap-package --channel=beta
. Старайтесь до победного - программа работает в strict ограничениях!if [ "$SNAP_ARCH" == "amd64" ]; then ARCH="x86_64-linux-gnu" elif [ "$SNAP_ARCH" == "armhf" ]; then ARCH="arm-linux-gnueabihf" else ARCH="$SNAP_ARCH-linux-gnu" fi
В моём случае (одна архитектура в лице 64 бит) итоговое имя файла будет osddm_4.1.3.901-snap1_amd64.snap.
Следующим шагом в snapcraft.yaml добавляем раздел apps и в него свои "программы".
apps: osddm: command: usr/bin/run.sh plugs: [network, network-bind, x11, home, unity7, gsettings]
Заметьте что имя "бинарника" osddm совпадает с именем пакета, что позволит пользователю вызывать программу по имени osddm, что неявно вызовет osddm.osddm. Некоторых коробит такой вид программы в стиле $имя_снап.$имя_программы, но вы должны понять, что внутри snap пакета могут идти несколько "программ", должен быть способ вызвать их и нужно решить вопрос с возможным совпадением одинаковых имён программ из разных пакетов. Ведь вы можете представить в системе программу music-player и другой снапкрафтер в своём пакете ненамеренно представить плеер с таким же именем.
Чтобы окончательно прояснить вопрос со множеством "бинарников" в снап пакете, представлю вам эталонный hello-world пакет.
sudo snap install hello-world ; cd /snap/hello-world/current/ ; tree
.
. ├── bin ← this directory structure is just for convenience │ ├── echo there is no hardcoded structure requirement other │ ├── env than meta/snap.yaml │ ├── evil │ ├── sh │ ├── showdev │ └── usehw └── meta ← your snap must have this directory ├── icon.png ← no prizes for guessing what this is └── snap.yaml ← this is the required metadata
В его snapcraft.yaml (в пакете он лежит как meta/snap.yaml) раздел apps выглядит так
apps: env: command: bin/env evil: command: bin/evil sh: command: bin/sh hello-world: command: bin/echo
Но возвращаемся к Oracle SQL Developer Data Modeler и к строкам
command: usr/bin/run.sh plugs: [network, network-bind, x11, home, unity7, gsettings]
Почему run.sh намекает на bash скрипт и там не указан бинарник программы? Дело в том, что snapcraft автоматически предоставляет очень куцый, по крайней мере пока, скрипт-враппер command-osddm.wrapper, который будет лежать в корне snap пакета и в нём строки:
#!/bin/sh export PATH="$SNAP/bin:$SNAP/usr/bin:$PATH" export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$SNAP/lib:$SNAP/usr/lib:$SNAP/lib/x86_64-linux-gnu:$SNAP/usr/lib/x86_64-linux-gnu" export LD_LIBRARY_PATH="$SNAP/usr/lib/x86_64-linux-gnu/mesa-egl:$SNAP/usr/lib/x86_64-linux-gnu/mesa:$LD_LIBRARY_PATH" export LD_LIBRARY_PATH="$SNAP/usr/lib/x86_64-linux-gnu:$SNAP/usr/lib/x86_64-linux-gnu/pulseaudio:$LD_LIBRARY_PATH" LD_LIBRARY_PATH=$SNAP_LIBRARY_PATH:$LD_LIBRARY_PATH exec "$SNAP/usr/bin/run.sh" "$@"
Как вы видите там реально базовые вещи в лице переменных PATH и LD_LIBRARY_PATH. Этого, к сожалению, не достаточно. По опыту скажу, что между стандартным враппером и запуском программы очень нужен ещё один ваш враппер-скрипт, которые подрихтует напильником нужное. Обратите внимание, что путь к программе (стартовому скрипту) в snapcraft.yaml указан в "относительном" стиле без / впереди - usr/bin/run.sh. usr/bin/ намекает, что это не системный /usr/, а usr/ внутри snap пакета. Обратите внимание, что в стандартном враппере наш путь был преобразован в exec $SNAP/usr/bin/run.sh. Переменная $SNAP хранит значение пути, куда будет установлен snap пакет. Обычно это /snap/$SNAP_NAME/$SNAP_REVISION/, то есть $SNAP = /snap/$SNAP_NAME/$SNAP_REVISION/. Содержимое run.sh будет ниже.
Что такое plugs и с чем его едят? Snap пакет самодостаточен и в нём нет понятия зависимости из мира deb как класс. Но будучи изолированным, софту нужно получать доступ к вещам за пределами тюрьмы-снап-пакета. По умолчанию, система (снап пакет ubuntu-core) предоставляет следующие слоты: camera, cups-control, firewall-control, gsettings, hardware-observe, home, locale-control, log-observe, modem-manager, mount-observe, network, network-bind, network-control, network-manager, network-observe, opengl, optical-drive, ppp, pulseaudio, snapd-control, system-observe, timeserver-control, timezone-control, unity7, x11. К нужным для вас слотам можно сделать connect и получить требуемое.
Заранее из snapcraft.yaml connect'ы просятся именно так - plugs: [network, network-bind, x11, home, unity7, gsettings]
В данном примере просим дать сетевой доступ network, возможность bind на сетевой интерфейс аля сервис - network-bind, возможность графической программе через свои тулкиты отобразить в X11, доступ к домашней папке home, доступ к технологиям Unity типа глобального меню и т.д., доступ к gsettings даст так же возможность общения по шине DBus.
Пользователь в дальнейшем может добавить коннекты или разорвать существующие. Пока это возможно только в консоли через snap connect/disconnect, но разработчиками планируется создание графической утилиты. Естественно, что разрыв соединения точно приведёт в потери части функционала программы и даже к её неработоспособности в ряде случаев. Например, в почтовой рассылке разработчиков читал что текущая реализация дисконнекта слота network очень груба и многие сетевые программы справедливо ругаются и падают, когда им отсекают их сетевые возможности. Разрабы хотят сделать реализацию отъёма слота network в стиле - "нет провода". То есть, отняв у сетевой программы коннект к слоту network, мы как бы говорим программе, что внутри её тюрьмы есть сетевая карта, но из неё "вынули провод".
Parts - это ваши кусочки с произвольными именами, которые делают полезные для вас вещи. Snapcraft расширяется через систему плагинов и команда snapcraft list-plugins
выводит на данный момент:
ant catkin copy jdk kernel maven nodejs python3 tar-content autotools cmake go kbuild make nil python2 scons
Добавляю раздел parts и первый кусочек dm-files, который использует плагин copy для размещения нужных файлов и каталогов в нужных местах.
parts: dm-files: plugin: copy files: run.sh: usr/bin/run.sh ddm/* : / ddm/opt/datamodeler/datamodeler.desktop : usr/share/applications/datamodeler.desktop ddm/opt/datamodeler/osddm.png : usr/share/icons/hicolor/128x128/apps/osddm.png after: [integration]
Разберём подробнее:
. ├── opt/ │ └── datamodeler/ │ ├── configuration/ │ ├── datamodeler/ │ ├── datamodeler.desktop │ ├── datamodeler.exe │ ├── datamodeler.sh* │ ├── dropins/ │ ├── dvt/ │ ├── equinox/ │ ├── external/ │ ├── icon.png │ ├── ide/ │ ├── jdbc/ │ ├── jdev/ │ ├── jlib/ │ ├── modules/ │ ├── netbeans/ │ ├── osddm.png │ ├── rdbms/ │ ├── sleepycat/ │ ├── sqldeveloper/ │ ├── svnkit/ │ └── userfiles/ └── usr/ └── local/ └── bin/
Прошу всё содержимое ddm/* разместить в корне /, но это корень снап пакета программы, а на корень / системы. Это важная грань и её следует понимать. Меня устраивает будущий путь к рабочему каталогу программы opt/datamodeler/ и всё остальное будет отталкиваться от этого.
[Desktop Entry] Encoding=UTF-8 Name=Oracle Data Modeler Comment=Oracle Data Modeler Icon=osddm.png Exec=run.sh Terminal=false Type=Application
Убрал абсолютные пути. Абсолютные пути, начинающиеся с /, обычно ошибка, так как это означает, что кто-то или что-то будет искать указанное с корня системы и получит отлуп от системы мандатного доступа AppArmor. Параметр Icon содержит только упоминание имени файла без пути, так как ниже мы попросим скопировать иконку в нужное место. Параметр Exec указывает на мой враппер, лежащий в usr/bin/ и находящийся в переменной PATH.
Кусочек по имени integration использует ничего не делающий плагин nil, чтобы с помощью stage-packages можно было указать какие пакеты из стандартных репозиториев Ubuntu snapcraft должен скачать и добавить их содержимое в будущий snap пакет. Вы ещё не забыли что снап пакет должен быть самодостаточным? "Всё своё ношу с собой".
integration: plugin: nil stage-packages: - gnome-icon-theme - file - sed - bash - openjdk-8-jre - locales - fonts-freefont-ttf - libxkbcommon0 - ttf-ubuntu-font-family - dmz-cursor-theme - light-themes - shared-mime-info - libgtk2.0-0 - libgdk-pixbuf2.0-0 - libglib2.0-bin - unity-gtk2-module - libcanberra-gtk-module - libc-bin - libx11-6 - libxtst6 - zlib1g - libc6
Здесь нужно сделать перерыв и объяснить один момент. Инструмент упаковки snapcraft находится под активной разработкой, как и вся новая технология пакетов snap. Вся эта братия находится на переднем фронте разработки и не может не содержать багов и шероховатостей. В моём случае из ТРЁХ плагинов (ant, maven, jdk), занимающиеся Java программами, в идеале нужно было взять jdk, который помогает в упаковке Java программ в готовых jar файлах. Ant и maven помогают в сборке Java программ из исходников.
Если сделать дополнительный кусочек java-files вот так
java-files: plugin: jdk source: .
то Snapcraft "увидит" Java природу упаковываемой программы и :
К этому моменту разработчики облегчили жизнь снапкрафтерам и представили облачные кусочки (cloud parts), которые легко использовать, добавив к любому своему кусочку строку
after: [desktop/xxx]
где xxx - gtk2, gtk3, qt4, qt5, glib-only.
Облачные кусочки (cloud parts) - это эталонный набор пакетов в раздел stage-packages и эталонный враппер desktop-launch.
Но на определённом этапе, snapcraft начал выводит сообщение, что разные мои кусочки и задействованные облачные кусочки начали добавлять одно и тоже, создав конфликт. Строка сообщения гласила что-то типа
Parts 'desktop/gtk3' and 'java-files' have the following file paths in common which have different contents:
usr/share/pkgconfig/shared-mime-info.pc
Нашёл открытый отчёт о баге Same packages pulled twice with different timestamps cause clash и подтвердил, добавив комментарий. Баг на дату написания статьи остаётся не закрытым и в состоянии High. Ну что можно сказать, кроме слова б%№ть? Сидеть ждать от моря погоды?
Решил:
Это легко сказать и трудно сделать. Выбросив помощь разработчиков в лице их cloud parts, лишился ещё и их эталонного враппера desktop-launch, которые делает такие вещи, до которых мне своим умом просто не дойти. Спёр эталонный desktop-launch и под видом run.sh с моими дополнениями он будет рассмотрен ниже. Так же спёр эталонный набор пакетов, просто добавив их в свой кусочек integration. Давайте вернёмся к нашим баранам.
Осталось вызвать snapcraft команду в папке с файлом snapcraft.yaml и всё? Щазззз. В идеальном мире вы могли бы указать источник программы в yaml, snapcraft скачал его и упаковал в готовый snap пакет вместе с нужными файлами. В идеальном мире снапкрафтер мог бы поделится созданным snapcraft.yaml с апстримом проекта и они уже сами легко паковали программу. Но реальный мир суров - нужно подправить различные нюансы в программе и её ручонки аккуратно завернуть внутрь смирительной рубашки.
Программа вместе со своей свитой внутри снап пакета будет сжата squashfs и доступна ТОЛЬКО-ДЛЯ-ЧТЕНИЯ по пути в переменной $SNAP. Для ЗАПИСИ чего-либо у вас будет путь $SNAP_USER_DATA.
Всё, игра началась! Так как упаковка даже готовой программы в jar файлах долгий процесс и исследование неизвестной программы без исходников чревато множеством итераций упаковки, то делаем ход конём. Копируем программу со сборочного сервера в свою основную систему в системный путь /opt/datamodeler/ и делаем 99% имитацию будущего положения: каталог для чтения, где обитает программа, и каталог для записи в лице ~/. Каталог /opt/datamodeler/ имитирует $SNAP, а ~/ имитирует $SNAP_USER_DATA.
Делаем для чистоты эксперимента владельцем каталога пользователя root и добавляем, чтобы файлы на чтение точно были доступны всем (a+r).
sudo chown -R root:root /opt/datamodeler/
sudo chmod -R a+r /opt/datamodeler/
Теперь осталось за малым . Нужно, чтобы запущенный из под обычного пользователя, Oracle SQL Developer Data Modeler корректно работал. Он может создавать в моей домашней папке ~/ что ему угодно, но он не должен и не сможет создавать или писа́ть в каталог /opt/datamodeler/.
Начнём исследование!
Стартовый для Linux систем скрипт opt/datamodeler/datamodeler.sh содержит cd "`dirname $0`"/datamodeler/bin && bash datamodeler
М-м-м, определяется где находится программа в данный момент и осуществляется переход в datamodeler/bin и запуск "bash datamodeler". Так и запишем в stage-packages, что требуется одноименный пакет bash, который хранит оболочку bash.
Анализируем вызываемый bash скрипт opt/datamodeler/datamodeler/bin/datamodeler. Ищём намёки на абсолютные пути. Вроде нет их. Шапка скрипта
#----------------------------------------------------------------------------- # toAbsPath() takes two arguments # 1) a pathname (assumed to point to a file) # 2) a directory that the pathname is relative to # # and converts the pathname to an absolute path (if necessary), resolving # any "." or ".." in the absolute path. The result is echoed to STDOUT. #-----------------------------------------------------------------------------
и всякие dirname и basename укрепляют нас в вере, что разработчики продумали тот момент, что их детище будет запущено из различных мест в файловой системе. Нам это на руку. Строка
"`dirname "${SCRIPT}"`/../../ide/bin/launcher.sh"
и вот мы двигаемся к другому скрипту launcher.sh, лежащему в opt/datamodeler/ide/bin/.
Launcher.sh не просто скрипт, а скриптище! Особого желания его править нет, но придётся. Множество вызовов программ с абсолютными путями. Сейчас это работает в моей хостовой системе, а внутри снап пакета - НЕТ! Пока ничего не трогаем, так как цель - не погрязнуть в переписывании скрипта. Находим традиционный розыск установленной Java машины.
# Search for Java in the following order: # 0) $OIDE_JAVA_HOME. This serves as a global override. # 1) ../../jdk/bin/java. Some products have a shipped JDK in this directory. # 2) ../../../jdk/bin/java. Some products have a shipped JDK in this # directory, and it points to the JDK for JDEVADF internal developers. # 3) $JAVA_HOME/bin/java. If JAVA_HOME is set, we should use that # to determine the JDK to use. # 4) A java in /usr/java/jdk8* # 5) A java in /usr/java8* (AIX) # 6) Any java on the PATH.
Мы можем через OIDE_JAVA_HOME или JAVA_HOME указать путь к Джава машине. В своём враппере run.sh делаю первые наброски: указываю путь к Java через JAVA_HOME и этот путь добавляю в PATH. Полный run.sh будет ниже.
export JAVA_HOME="$SNAP/usr/lib/jvm/java-8-openjdk-amd64/" export PATH="$JAVA_HOME:$SNAP/usr/lib/x86_64-linux-gnu/:$SNAP/opt/datamodeler/datamodeler/bin:$SNAP/usr/lib/jvm/java-8-openjdk-amd64/bin:$SNAP/opt/datamodeler/ide/bin:$PATH" ... exec $SNAP/opt/datamodeler/datamodeler.sh
Пробуем создать snap пакет на сборочном сервере с помощью snapcraft. В тестовой виртуальной машине с Ubuntu 16.04 LTS ставим первый билд - sudo snap install --devmode osddm_4.1.3.901-snap1_amd64.snap
. И первый блин комом! Запуск osddm требует указать путь к JDK, хотя моя хостовая машина ничего не выводила. По тексту сообщения вышел на кусок кода в launcher.sh, где прямо говорилось, что если предоставляемая Java машина обладает нужным, то просто добавьте SetSkipJ2SDKCheck true. Но куда это добавлять? Нашёл строку
setskipj2sdkcheck) NEWARG="SetSkipJ2SDKCheck" ;;
и попробовал в opt/datamodeler/datamodeler.sh добавить cd "`dirname $0`"/datamodeler/bin && bash datamodeler --setskipj2sdkcheck
Но номер у меня не удался. Помог другой способ. Если строка SetSkipJ2SDKCheck true есть в файле .data_modeler/1.0.0.0.0/product.conf, то osddm перестаёт ругаться. В run.sh нужно добавить строки ДО вызова программы
mkdir -p "$SNAP_USER_DATA/.data_modeler/1.0.0.0.0" echo "SetSkipJ2SDKCheck true" > "$SNAP_USER_DATA/.data_modeler/1.0.0.0.0/product.conf"
На этом этапе osddm стартовал, быстро мелькал сплэш экран и всё - программа завершалась. Добавил --verbose в opt/datamodeler/datamodeler.sh - cd "`dirname $0`"/datamodeler/bin && bash datamodeler --verbose
. В launcher.sh заработали строки EchoIfVerbose, которые стали выводить не лишнюю для меня информацию, но понимание ситуации не улучшили. В данном месте стало грустно. У меня на руках Java программа, а я не разбираюсь ни в Джава, ни в данной программе. Отлаживать программы никогда не умел. Взгляд упал на файл opt/datamodeler/datamodeler/bin/logging.conf, чьё название намекает на конфигурирование уровня журналирования. Нужно поднять уровень журналирования! На просторах Интернет нашёл советы от профи - как повысить уровень информирования в консоль о ходе работы джава программы.
Внёс строки
.level=SEVERE java.util.logging.ConsoleHandler.level=ALL java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter oracle.dbtools.logging.LogPaneHandler.level=ALL
И? Строк стало так много, что старт программы замедлился в разы ! Но теперь хотя бы можно найти проблему. Оказалось, что такой сложный комплекс как Oracle SQL Developer Data Modeler состоит из различных компонент и один из них обнаружил, что его каталог opt/datamodeler/netbeans/platform/ находится на разделе со свободным местом в 0 байт. То есть он ругается не на то, что каталог не доступен для записи, а именно что каталог находится там где свободного места = 0 байт.
И как быть? Мысль только одна. Нужно вынести каталог platform/ в $SNAP_USER_DATA/ и заюзать его оттуда. В run.sh пишу прототип, если нет platform при первом запуске программы, то копирую нужное.
if [ ! -e "$SNAP_USER_DATA/platform" ]; then
mkdir -p "$SNAP_USER_DATA/platform"
cp --preserve=timestamps -dR "$SNAP/opt/datamodeler/netbeans/platform" "$SNAP_USER_DATA"
fi
А кто юзает каталог platform? Оказалось в opt/datamodeler/ide/bin/ide.conf нужно подправить часть строк
AddJavaLibFile ${SNAP_USER_DATA}/platform/lib/boot.jar AddJavaLibFile ${SNAP_USER_DATA}/platform/lib/org-openide-util-ui.jar AddJavaLibFile ${SNAP_USER_DATA}/platform/lib/org-openide-util.jar AddJavaLibFile ${SNAP_USER_DATA}/platform/lib/org-openide-util-lookup.jar AddJavaLibFile ${SNAP_USER_DATA}/platform/lib/org-openide-modules.jar AddVMOption -Dnetbeans.home=${SNAP_USER_DATA}/platform/
И? На тебе под дых, чтобы не расслаблялся. Oracle SQL Developer Data Modeler стал ругаться, что его домашняя папка, которая расположена в $SNAP_USER_DATA совпадает с путём к platform. Нуёптвоюмать! Нужна срочно ещё папка для записи. Недавно введена папка, которая не поддерживает версионность, и доступна через переменную $SNAP_USER_COMMON = /home/$user/snap/$app-name/common/. Но вызов в скрипте run.sh
mkdir -p "$SNAP_USER_COMMON"
вызывал отказ в доступе. Кинулся к разрабам в почтовой рассылке - ответ просто убил. Это типа бага, пока вызывайте snap run ossdm; ossdm
. Хорошо что я плохо выражаю свои мысли на английском и тем более отборные маты. Ну как так-то? Вместо красивого вызова программы osddm, просить пользователя однократно вызывать snap run ossdm; ossdm
? И где мне это просить? Быть в шаге от победы и отложить на неопределённый срок упаковку программы, которая готова на 99,99%. Р-р-р.
Так просто не сдамся, вдумчиво старался понять последний вызов мне. Что точно не нравится Oracle SQL Developer Data Modeler? Осенило, что ему не нравится тот факт, что папка $SNAP_USER_DATA/platform/ НА ОДНОМ УРОВНЕ иерархии с папкой $SNAP_USER_DATA/.oraclesqldeveloperdatamodeler/. Окей, бэби! Сдвигаю папку platform вглубь - ${SNAP_USER_DATA}/deep/platform/. Бинго! Oracle SQL Developer Data Modeler милостиво дал добро и запустился во всей красе. Прошёл эту игру, замочил босса на уровне.
В процессе тестирования работы программы в ограниченной профилями AppArmor среде вырисовалась маленькая шероховатость. Oracle SQL Developer Data Modeler при сохранении вашей работы, пытается осуществлять частичную запись в каталог, откуда он стартовал и естественно в этом ему отказано. Оказалось есть переменные в конфигурационном файле, которые помогут переопределить нужные папки. Это переменная def_sys_types_path. Создал дефолтный прообраз будущего конфигурационного файла ddm/opt/datamodeler/userfiles/product-preferences.xml и значения заполнил метками, которые заменит sed при первом старте программы.
В run.sh есть строки
mkdir -p "$SNAP_USER_DATA/.oraclesqldeveloperdatamodeler/system4.1.3.901/o.datamodeler" UUID=$(cat /proc/sys/kernel/random/uuid) # меняем XYZZYX на ${SNAP_USER_DATA}/tmp sed "s#XYZZYX#${SNAP_USER_DATA}/tmp#g" "$SNAP/opt/datamodeler/userfiles/product-preferences.xml" | tee -a "$SNAP_USER_DATA/.oraclesqldeveloperdatamodeler/system4.1.3.901/o.datamodeler/product-preferences2.xml" # меняем ZXCCXZ на заранее полученный UUID sed "s#ZXCCXZ#${UUID}#g" "$SNAP_USER_DATA/.oraclesqldeveloperdatamodeler/system4.1.3.901/o.datamodeler/product-preferences2.xml" | tee -a "$SNAP_USER_DATA/.oraclesqldeveloperdatamodeler/system4.1.3.901/o.datamodeler/product-preferences.xml" # копируем нужный файл types.xml в каталог def_sys_types_path (${SNAP_USER_DATA}/tmp) cp --preserve=timestamps "$SNAP/opt/datamodeler/datamodeler/types/types.xml" "$SNAP_USER_DATA/tmp/types.xml"
Манипуляции с параметром instanceGuid нужны, чтобы у разных пользователей был различный UUID, что важно в определённых местах. Хотелось сделать всем красиво. Разные UUID - это правильно.
Всё ли сделано? Из задуманного - всё. Программа корректно стартует и работает, сохраняя результаты пользователя. В данный момент можно получить через процедуру Update много вкусняшек к программе (~1,5 Гб), но корректно установить нельзя, так как каталог программы доступен только на чтение. Поэтому временно отключил проверку обновлений на старте. Такой серьёзный вызов требует серьёзного подхода и оставлен на вторую битву с Oracle SQL Developer Data Modeler. Нужно разместить скачанное в $SNAP_USER_DATA и подключить к программе. Постараюсь реализовать, но не обещаю, что справлюсь с таким вызовом.
На этом всё! Желаю всем поиграть в эту игру - "Snapcraft. Упакуй Рой"
Первый snap пакет. Java программа LanguageTool. sudo snap install languagetool
Второй snap пакет. GTK программа DeaDBeeF. sudo snap install deadbeef-vs
Третий snap пакет. Java программа TuxGuitar. sudo snap install tuxguitar-vs
Четвёртый snap пакет. Java программа Vuze. sudo snap install vuze-vs
Пятый snap пакет. Java программа osddm. sudo snap install osddm
Шестой snap пакет. PAC (Perl Auto Connector). sudo snap install pac-vs
Все пакеты в Ubuntu Store.
snap find vs
Name Version Developer Notes Summary deadbeef-vs 0.7.2-snap1 vs - The Ultimate Music Player languagetool 3.4-snap2 vs - LanguageTool osddm 4.1.3.901-snap1 vs - Oracle SQL Developer Data Modeler tuxguitar-vs 1.3.2-snap2 vs - TuxGuitar vuze-vs 5.7.2.0-snap1 vs - Vuze is a powerful, open source, bittorrent client.
Полностью snapcraft.yaml.
name: osddm version: "4.1.3.901-snap1" summary: Oracle SQL Developer Data Modeler description: | Oracle SQL Developer Data Modeler is a free graphical tool that enhances productivity and simplifies data modeling tasks. Using Oracle SQL Developer Data Modeler users can create, browse and edit, logical, relational, physical, multi-dimensional, and data type models. The Data Modeler provides forward and reverse engineering capabilities and supports collaborative development through integrated source code control. The Data Modeler can be used in both traditional and in Cloud environments. confinement: strict architectures: [amd64] apps: osddm: command: usr/bin/run.sh plugs: [network, network-bind, x11, home, unity7, gsettings] parts: dm-files: plugin: copy files: run.sh: usr/bin/run.sh ddm/* : / ddm/opt/datamodeler/datamodeler.desktop : usr/share/applications/datamodeler.desktop ddm/opt/datamodeler/osddm.png : usr/share/icons/hicolor/128x128/apps/osddm.png after: [integration] integration: plugin: nil stage-packages: - gnome-icon-theme - file - sed - bash - openjdk-8-jre - locales - fonts-freefont-ttf - libxkbcommon0 - ttf-ubuntu-font-family - dmz-cursor-theme - light-themes - shared-mime-info - libgtk2.0-0 - libgdk-pixbuf2.0-0 - libglib2.0-bin - unity-gtk2-module - libcanberra-gtk-module - libc-bin - libx11-6 - libxtst6 - zlib1g - libc6
Полностью run.sh, основанный на эталонном desktop-launch от разработчиков. Мой вклад начинается со строки vasilisc part, так как англоязычные разработчики не утруждают себя вопросами локализации.
#!/bin/bash echo "Please wait, this may take a minute. " ############################################### # Launcher common exports for any desktop app # ############################################### export JAVA_HOME="$SNAP/usr/lib/jvm/java-8-openjdk-amd64/" export PATH="$JAVA_HOME:$SNAP/usr/lib/x86_64-linux-gnu/:$SNAP/opt/datamodeler/datamodeler/bin:$SNAP/usr/lib/jvm/java-8-openjdk-amd64/bin:$SNAP/opt/datamodeler/ide/bin:$PATH" export UBUNTU_MENUPROXY= needs_update=true . ~/.last_revision 2>/dev/null || true if [ "$SNAP_DESKTOP_LAST_REVISION" = "$SNAP_REVISION" ]; then needs_update=false fi [ $needs_update = true ] && echo "SNAP_DESKTOP_LAST_REVISION=$SNAP_REVISION" > ~/.last_revision if [ "$SNAP_ARCH" == "amd64" ]; then ARCH="x86_64-linux-gnu" elif [ "$SNAP_ARCH" == "armhf" ]; then ARCH="arm-linux-gnueabihf" else ARCH="$SNAP_ARCH-linux-gnu" fi # XKB config export XKB_CONFIG_ROOT=$SNAP/usr/share/X11/xkb # Mesa Libs export LD_LIBRARY_PATH=$SNAP/usr/lib/$ARCH/mesa:$LD_LIBRARY_PATH export LD_LIBRARY_PATH=$SNAP/usr/lib/$ARCH/mesa-egl:$LD_LIBRARY_PATH # Tell libGL where to find the drivers export LIBGL_DRIVERS_PATH=$SNAP/usr/lib/$ARCH/dri export LD_LIBRARY_PATH=$SNAP/usr/lib/x86_64-linux-gnu/:$SNAP/usr/lib/$ARCH/dri:$LD_LIBRARY_PATH # Pulseaudio export export LD_LIBRARY_PATH=$SNAP/usr/lib/$ARCH/pulseaudio:$LD_LIBRARY_PATH # XDG Config export XDG_CONFIG_DIRS=$SNAP/etc/xdg:$SNAP/usr/xdg:$XDG_CONFIG_DIRS # Define snaps' own data dir export XDG_DATA_DIRS=$SNAP_USER_DATA:$SNAP/usr/share:$XDG_DATA_DIRS # Set XDG_DATA_HOME to local path export XDG_DATA_HOME=$SNAP_USER_DATA/.local/share export XDG_DATA_DIRS=$XDG_DATA_HOME:$XDG_DATA_DIRS mkdir -p $XDG_DATA_HOME # Set cache folder to local path export XDG_CACHE_HOME=$SNAP_USER_DATA/.cache mkdir -p $XDG_CACHE_HOME # Font Config and themes export FONTCONFIG_PATH=$SNAP/etc/fonts/conf.d export FONTCONFIG_FILE=$SNAP/etc/fonts/fonts.conf if [ $needs_update = true ]; then rm -rf $XDG_DATA_HOME/{fontconfig,fonts,fonts-*,themes} ln -sf $SNAP/usr/share/{fontconfig,fonts,fonts-*,themes} $XDG_DATA_HOME ln -sf $SNAP/usr/share/themes $SNAP_USER_DATA/.themes fi # Build mime.cache # needed for gtk and qt icon if [ $needs_update = true ]; then rm -rf $XDG_DATA_HOME/mime if [ `which update-mime-database` ]; then cp --preserve=timestamps -dR $SNAP/usr/share/mime $XDG_DATA_HOME update-mime-database $XDG_DATA_HOME/mime fi fi ############################## # GTK launcher specific part # ############################## # select gtk version #. $SNAP/flavor-select USE_gtk3=false # Gdk-pixbuf loaders export GDK_PIXBUF_MODULE_FILE=$XDG_CACHE_HOME/gdk-pixbuf-loaders.cache export GDK_PIXBUF_MODULEDIR=$SNAP/usr/lib/$ARCH/gdk-pixbuf-2.0/2.10.0/loaders if [ $needs_update = true ]; then rm -f $GDK_PIXBUF_MODULE_FILE $SNAP/usr/lib/$ARCH/gdk-pixbuf-2.0/gdk-pixbuf-query-loaders > $GDK_PIXBUF_MODULE_FILE fi # Gio modules and cache export GIO_MODULE_DIR=$XDG_CACHE_HOME/gio-modules if [ $needs_update = true ]; then rm -rf $GIO_MODULE_DIR mkdir -p $GIO_MODULE_DIR ln -s $SNAP/usr/lib/$ARCH/gio/modules/*.so $GIO_MODULE_DIR $SNAP/usr/lib/$ARCH/glib-2.0/gio-querymodules $GIO_MODULE_DIR fi # GI repository export GI_TYPELIB_PATH=$SNAP/usr/lib/girepository-1.0:$SNAP/usr/lib/$ARCH/girepository-1.0 if [ "$USE_gtk3" = true ]; then export GTK_PATH=$SNAP/usr/lib/$ARCH/gtk-3.0 else export GTK_PATH=$SNAP/usr/lib/$ARCH/gtk-2.0 fi # ibus and fcitx integration # with those defintions fcitx works unconfined out of the box, ibus requires # user config to be copied though, https://launchpad.net/bugs/1580463 GTK_IM_MODULE_DIR=$XDG_CACHE_HOME/immodules export GTK_IM_MODULE_FILE=$GTK_IM_MODULE_DIR/immodules.cache if [ $needs_update = true ]; then rm -rf $GTK_IM_MODULE_DIR mkdir -p $GTK_IM_MODULE_DIR if [ "$USE_gtk3" = true ]; then ln -s $SNAP/usr/lib/$ARCH/gtk-3.0/3.0.0/immodules/*.so $GTK_IM_MODULE_DIR $SNAP/usr/lib/$ARCH/libgtk-3-0/gtk-query-immodules-3.0 > $GTK_IM_MODULE_FILE else ln -s $SNAP/usr/lib/$ARCH/gtk-2.0/2.10.0/immodules/*.so $GTK_IM_MODULE_DIR $SNAP/usr/lib/$ARCH/libgtk2.0-0/gtk-query-immodules-2.0 > $GTK_IM_MODULE_FILE fi fi # Keep an array of data dirs, for looping through them IFS=':' read -r -a data_dirs_array <<< "$XDG_DATA_DIRS" # Setup compiled gsettings schema GS_SCHEMA_DIR=$XDG_DATA_HOME/glib-2.0/schemas if [ $needs_update = true ]; then rm -rf $GS_SCHEMA_DIR mkdir -p $GS_SCHEMA_DIR for d in "${data_dirs_array[@]}"; do schema_dir=$d/glib-2.0/schemas if [ "$(ls -A $schema_dir/*.xml 2>/dev/null)" ]; then ln -s $schema_dir/*.xml $GS_SCHEMA_DIR fi done $SNAP/usr/lib/$ARCH/glib-2.0/glib-compile-schemas $GS_SCHEMA_DIR fi # Enable gsettings user changes # symlink the dconf file if home plug is connected for read DCONF_DEST_USER_DIR=$SNAP_USER_DATA/.config/dconf if [ ! -f $DCONF_DEST_USER_DIR/user ]; then if [ -f /home/$USER/.config/dconf/user ]; then mkdir -p $DCONF_DEST_USER_DIR ln -s /home/$USER/.config/dconf/user $DCONF_DEST_USER_DIR fi fi # Icon themes cache if [ $needs_update = true ]; then rm -rf $XDG_DATA_HOME/icons mkdir -p $XDG_DATA_HOME/icons for d in "${data_dirs_array[@]}"; do for i in $d/icons/*; do if [ -d "$i" ]; then theme_dir=$XDG_DATA_HOME/icons/$(basename "$i") if [ ! -d "$theme_dir" ]; then mkdir -p "$theme_dir" ln -s $i/* "$theme_dir" if [ -f $SNAP/usr/sbin/update-icon-caches ]; then $SNAP/usr/sbin/update-icon-caches "$theme_dir" elif [ -f $SNAP/usr/sbin/update-icon-cache.gtk2 ]; then $SNAP/usr/sbin/update-icon-cache.gtk2 "$theme_dir" fi fi fi done done fi # vasilisc part ###################################### export I18NPATH=$SNAP/usr/share/i18n export LOCPATH=$SNAP_USER_DATA export LC_ALL=$LANG LANG1=$(echo $LANG | cut -f1 -d.) ENC=UTF-8 LOC="$LANG" # generate a locale so we get properly working charsets and graphics if [ ! -e $SNAP_USER_DATA/$LOC ]; then $SNAP/usr/bin/localedef --prefix=$SNAP_USER_DATA -f $ENC -i $LANG1 $SNAP_USER_DATA/$LOC fi ###################################### if [ ! -e "$SNAP_USER_DATA/debug" ]; then mkdir -p "$SNAP_USER_DATA/debug" mkdir -p "$SNAP_USER_DATA/tmp" printenv > "$SNAP_USER_DATA/debug/debug.log" fi if [ ! -e "$SNAP_USER_DATA/deep/platform" ]; then mkdir -p "$SNAP_USER_DATA/deep/platform" cp --preserve=timestamps -dR "$SNAP/opt/datamodeler/netbeans/platform" "$SNAP_USER_DATA/deep/" mkdir -p "$SNAP_USER_DATA/.data_modeler/1.0.0.0.0" echo "SetSkipJ2SDKCheck true" > "$SNAP_USER_DATA/.data_modeler/1.0.0.0.0/product.conf" mkdir -p "$SNAP_USER_DATA/.oraclesqldeveloperdatamodeler/system4.1.3.901/o.datamodeler" UUID=$(cat /proc/sys/kernel/random/uuid) sed "s#XYZZYX#${SNAP_USER_DATA}/tmp#g" "$SNAP/opt/datamodeler/userfiles/product-preferences.xml" | tee -a "$SNAP_USER_DATA/.oraclesqldeveloperdatamodeler/system4.1.3.901/o.datamodeler/product-preferences2.xml" sed "s#ZXCCXZ#${UUID}#g" "$SNAP_USER_DATA/.oraclesqldeveloperdatamodeler/system4.1.3.901/o.datamodeler/product-preferences2.xml" | tee -a "$SNAP_USER_DATA/.oraclesqldeveloperdatamodeler/system4.1.3.901/o.datamodeler/product-preferences.xml" cp --preserve=timestamps "$SNAP/opt/datamodeler/datamodeler/types/custom_report_templates.xml" "$SNAP_USER_DATA/tmp/custom_report_templates.xml" cp --preserve=timestamps "$SNAP/opt/datamodeler/datamodeler/types/defaultdomains.xml" "$SNAP_USER_DATA/tmp/defaultdomains.xml" cp --preserve=timestamps "$SNAP/opt/datamodeler/datamodeler/types/defaultRDBMSSites.xml" "$SNAP_USER_DATA/tmp/defaultRDBMSSites.xml" cp --preserve=timestamps "$SNAP/opt/datamodeler/datamodeler/types/dl_settings.xml" "$SNAP_USER_DATA/tmp/dl_settings.xml" cp --preserve=timestamps "$SNAP/opt/datamodeler/datamodeler/types/dr_custom_scripts.xml" "$SNAP_USER_DATA/tmp/dr_custom_scripts.xml" cp --preserve=timestamps "$SNAP/opt/datamodeler/datamodeler/types/old_defaultdomains.xml" "$SNAP_USER_DATA/tmp/old_defaultdomains.xml" cp --preserve=timestamps "$SNAP/opt/datamodeler/datamodeler/types/types.xml" "$SNAP_USER_DATA/tmp/types.xml" fi export TEMPDIR="$SNAP_USER_DATA/tmp" exec $SNAP/opt/datamodeler/datamodeler.shДата последней правки: 2023-12-27 12:49:08