Введение
Для корпоративного развёртывания (массовая установка на сотни рабочих станций через систему управления конфигурацией) или для автоматизированного CI/CD-пайплайна интерактивный установщик с мастером и диалогами неприемлем — нужна возможность установить приложение полностью без участия человека, передав все необходимые параметры через аргументы командной строки или конфигурационный файл. В статье разберём, как настроить и использовать молчаливую установку через QtIFW.
Концепция
QtIFW поддерживает несколько режимов неинтерактивной работы: --script для выполнения произвольного управляющего JavaScript-сценария, который программно «проходит» мастер установки без визуального отображения, и более простой unattended-режим с явным указанием выбранных компонентов и пути установки через аргументы командной строки. Для воспроизводимой, версионируемой конфигурации молчаливой установки часто используется отдельный XML-файл с заранее заданными ответами на все вопросы, которые обычно задаёт интерактивный мастер.
Пример кода: Молчаливая (silent) установка
# Простейший вариант молчаливой установки с указанием пути и компонентов
./MyAppInstaller --accept-licenses --confirm-command \
--root /opt/MyApp \
--default-answer \
install com.mycompany.myapp,com.mycompany.myapp.langpack.ru
// silent_install_control.qs — управляющий скрипт для полностью автоматизированной установки
function Controller()
{
installer.autoRejectMessageBoxes();
installer.installationFinished.connect(function() {
gui.clickButton(buttons.NextButton);
});
}
Controller.prototype.WelcomePageCallback = function()
{
gui.clickButton(buttons.NextButton);
};
Controller.prototype.TargetDirectoryPageCallback = function()
{
gui.currentPageWidget().TargetDirectoryLineEdit.setText("/opt/MyApp");
gui.clickButton(buttons.NextButton);
};
Controller.prototype.ComponentSelectionPageCallback = function()
{
var widget = gui.currentPageWidget();
widget.deselectAll();
widget.selectComponent("com.mycompany.myapp");
gui.clickButton(buttons.NextButton);
};
Controller.prototype.LicenseAgreementPageCallback = function()
{
gui.currentPageWidget().AcceptLicenseRadioButton.setChecked(true);
gui.clickButton(buttons.NextButton);
};
Controller.prototype.ReadyForInstallationPageCallback = function()
{
gui.clickButton(buttons.NextButton);
};
Controller.prototype.FinishedPageCallback = function()
{
gui.clickButton(buttons.FinishButton);
};
# Запуск установки через управляющий скрипт — установщик показывается,
# но все действия в нём выполняются программно без вмешательства человека
./MyAppInstaller --script silent_install_control.qs --platform minimal
# .gitlab-ci.yml — пример интеграции молчаливой установки в CI-пайплайн для тестирования
test_installation:
stage: test
script:
- ./MyAppInstaller --accept-licenses --confirm-command --root /tmp/test-install --default-answer install
- test -f /tmp/test-install/MyApp || exit 1
- echo "Установка прошла успешно, файл приложения найден"
Пояснения к коду
Первый вариант — самый простой случай, когда установщик поддерживает прямую неинтерактивную установку через флаги командной строки (--accept-licenses, --default-answer) без необходимости в отдельном управляющем скрипте — этот режим подходит для случаев, когда нужная конфигурация компонентов известна заранее и совпадает со значениями по умолчанию или может быть указана явно через простой список ID компонентов.
silent_install_control.qs показывает более гибкий, но и более многословный подход — управляющий скрипт, который программно отвечает на каждую страницу мастера установки через Callback-функции, соответствующие имени каждой конкретной страницы (WelcomePageCallback, TargetDirectoryPageCallback и так далее) — этот подход даёт точный контроль над каждым шагом, что важно, если установщик содержит кастомные страницы (как из статьи 211), для которых стандартного --default-answer было бы недостаточно. Флаг --platform minimal запускает установщик с минимальным, не требующим реального графического дисплея платформенным плагином Qt — это особенно важно для headless CI-окружений без доступного графического сервера.
Подводные камни
- Расхождение между поведением интерактивной и автоматизированной установки, если управляющий скрипт не покрывает абсолютно все возможные страницы и условные ветвления мастера установки (например, появление дополнительной страницы только при выборе определённого компонента) — скрипт, протестированный для одной конфигурации выбора компонентов, может неожиданно «застрять» на непредусмотренной странице при другой комбинации выбранных опций, если для неё не реализован соответствующий
Callback. - Использование
--default-answerбез понимания, что именно оно подставляет для каждого конкретного диалога. Этот флаг даёт разумные значения по умолчанию для типичных диалогов (принятие лицензии, путь установки по умолчанию), но не гарантирует предсказуемое поведение для полностью кастомных страниц мастера — для установщиков с нестандартными страницами почти всегда нужен явный управляющий скрипт, а не только общие флаги командной строки. - Запуск молчаливой установки от имени пользователя без достаточных прав на запись в выбранную целевую директорию (особенно при установке в системные директории, требующие повышенных прав) — автоматизированный скрипт деплоя должен явно учитывать необходимость запуска от администратора/root там, где это нужно, и сама молчаливая установка не освобождает от этого требования операционной системы.
- Отсутствие проверки кода возврата процесса установщика в автоматизированном пайплайне. Молчаливая установка, завершившаяся с ошибкой (например, недостаточно места на диске), всё равно может не выдать явно видимое сообщение в логе CI, если код возврата процесса не проверяется явно — пример CI-конфигурации показывает дополнительную проверку наличия установленного файла приложения после завершения процесса установки именно для того, чтобы не полагаться только на код возврата самого
binarycreator-собранного установщика, поведение которого в части кодов возврата при разных типах сбоев не всегда полностью однородно документировано.