Silent install Qt run installer on ubuntu server

QtInstallationUbuntu Server

Qt Problem Overview


I wanted to know if there is a way to do a silent install of the Qt run installer on Ubuntu Server?
I mean by-pass the options of the installer and do a default install?

Qt Solutions


Solution 1 - Qt

Updated Answer:

Newer Qt installers have a proper CLI that allows you to do something like:

qt-unified-windows-x86-4.2.0-online.exe ^
  --accept-licenses ^
  --default-answer ^
  --confirm-command install ^
  qt.qt5.5158.win64_msvc2019_64 ^
  qt.qt5.5158.qtcharts ^
  qt.qt5.5158.debug_info ^
  qt.qt5.5158.src ^
  qt.tools.qtcreator

See --help for all options. To figure out package names, go through a graphical install but stop at the final confirmation screen that lists the package names for all your selections.

Previous Answer

The Qt toolkit is packaged using the Qt Installer Framework (QtIFW). QtIFW installers support a --script option that allows you to programatically control the installation via the Controller Scripting API. Here's qt-installer-noninteractive.qs file to install Qt 5 non-interactively:

// Emacs mode hint: -*- mode: JavaScript -*-

function Controller() {
    installer.autoRejectMessageBoxes();
    installer.installationFinished.connect(function() {
        gui.clickButton(buttons.NextButton);
    })
}

Controller.prototype.WelcomePageCallback = function() {
    // click delay here because the next button is initially disabled for ~1 second
    gui.clickButton(buttons.NextButton, 3000);
}

Controller.prototype.CredentialsPageCallback = function() {
    gui.clickButton(buttons.NextButton);
}

Controller.prototype.IntroductionPageCallback = function() {
    gui.clickButton(buttons.NextButton);
}

Controller.prototype.TargetDirectoryPageCallback = function()
{
    gui.currentPageWidget().TargetDirectoryLineEdit.setText(installer.value("HomeDir") + "/Qt");
    gui.clickButton(buttons.NextButton);
}

Controller.prototype.ComponentSelectionPageCallback = function() {
    var widget = gui.currentPageWidget();

    widget.deselectAll();
    widget.selectComponent("qt.55.gcc_64");
    widget.selectComponent("qt.55.qtquickcontrols");

    // widget.deselectComponent("qt.tools.qtcreator");
    // widget.deselectComponent("qt.55.qt3d");
    // widget.deselectComponent("qt.55.qtcanvas3d");
    // widget.deselectComponent("qt.55.qtlocation");
    // widget.deselectComponent("qt.55.qtquick1");
    // widget.deselectComponent("qt.55.qtscript");
    // widget.deselectComponent("qt.55.qtwebengine");
    // widget.deselectComponent("qt.extras");
    // widget.deselectComponent("qt.tools.doc");
    // widget.deselectComponent("qt.tools.examples");

    gui.clickButton(buttons.NextButton);
}

Controller.prototype.LicenseAgreementPageCallback = function() {
    gui.currentPageWidget().AcceptLicenseRadioButton.setChecked(true);
    gui.clickButton(buttons.NextButton);
}

Controller.prototype.StartMenuDirectoryPageCallback = function() {
    gui.clickButton(buttons.NextButton);
}

Controller.prototype.ReadyForInstallationPageCallback = function()
{
    gui.clickButton(buttons.NextButton);
}

Controller.prototype.FinishedPageCallback = function() {
var checkBoxForm = gui.currentPageWidget().LaunchQtCreatorCheckBoxForm;
if (checkBoxForm && checkBoxForm.launchQtCreatorCheckBox) {
    checkBoxForm.launchQtCreatorCheckBox.checked = false;
}
    gui.clickButton(buttons.FinishButton);
}

This script demonstrates how to select/deselect certain components. Customize for your needs or just remove the lines entirely for a default installation. Likewise, you may want to customize or remove the TargetDirectoryLineEdit line. Run the Qt installer like:

qt-opensource-linux-x64-5.5.1.run --script qt-installer-noninteractive.qs

Add -platform minimal for a headless installation. Future installers based on newer versions of QtIFW should be able to use a --silent option instead (see QTIFW-166).

Add --verbose for more verbose console output (helpful for gleaning component names, wizard page names, etc). This link is also helpful for figuring out component names.

Solution 2 - Qt

As of installer 4.X, you don't need to play with JS files anymore. Version 4.0 of the Qt online installer has first-class support for headless installation. See this answer for more information.

As of installer 3.0.2-online 29-11-2017, you must add a delay in your JS script because the "Next" button in the "Welcome" page is disabled for one second or so.

Controller.prototype.WelcomePageCallback = function() {
    gui.clickButton(buttons.NextButton, 3000);
}

For once, they explain on the 3.2.1-online 29-01-2020 release page how to skip the new form

Controller.prototype.ObligationsPageCallback = function() {
    var page = gui.pageWidgetByObjectName("ObligationsPage");
    page.obligationsAgreement.setChecked(true);
    page.completeChanged();
    gui.clickButton(buttons.NextButton);
}

Some may wonder how to create the mysterious qtaccount.ini file (required since 3.2.1-2-online). Qt only tells us that it should be placed in ~/.local/share/Qt/. I was unable to find any other information. The installer creates this file itself when you enter your credentials for the first time. So simply do a manual installation and quit after the accound form. The generated file looks like

[General]
email[email protected]
pass=mypass

[QtAccount]
email[email protected]
jwt=a long hash
u=a small hash

Solution 3 - Qt

2020 update: There's a better way now.

Version 4.0 of the Qt online installer has first-class support for headless installation.

See this answer below for more info.


Original answer:

Bypassing "User Data Collection" screen

As of October 8, 2019, an extra screen has been added on Windows which will cause the installation to hang. You can click through it with the following addition to your .qs file:

Controller.prototype.DynamicTelemetryPluginFormCallback = function() {
    var widget = gui.currentPageWidget();
    widget.TelemetryPluginForm.statisticGroupBox.disableStatisticRadioButton.checked = true;
    gui.clickButton(buttons.NextButton);
}
Selecting "Archive" and "Latest releases"

Another recent change is to package categories. LTS is now the only one selected by default, meaning that you cannot install the latest Qt version without first selecting "Latest releases" in the package categories.

Here's how to do that:

Controller.prototype.ComponentSelectionPageCallback = function() {
    var page = gui.pageWidgetByObjectName("ComponentSelectionPage");

    var archiveCheckBox = gui.findChild(page, "Archive");
    var latestCheckBox = gui.findChild(page, "Latest releases");
    var fetchButton = gui.findChild(page, "FetchCategoryButton");

    archiveCheckBox.click();
    latestCheckBox.click();
    fetchButton.click();

    // ...
}

See here for a more complete example for Windows.

Solution 4 - Qt

There have few minor different in answering the questions of wizard for a different kind of version of Qt. To make it more simple, I have packed a generic script to extract Qt from an offline/online installer.

The script: qtci/extract-qt-installer at master · benlau/qtci

Example Usage:

extract-qt-installer qt-opensource-linux-x64-android-5.5.1.run ~/Qt

Environment Variables"

VERBOSE [Optional] Set to "true" will enable VERBOSE output
QT_CI_PAGEAGES [Optional] Select the components to be installed instead of using default (eg. QT_CI_PAGEAGES="qt.59.gcc_64")

Moreover, it has few scripts to download and install Qt with different versions.

qtci/recipes at master · benlau/qtci

Solution 5 - Qt

The script above is old. This should work (and I added retry for download errors)

function Controller() {
    installer.autoRejectMessageBoxes();
    installer.setMessageBoxAutomaticAnswer("installationError", QMessageBox.Retry);
    installer.setMessageBoxAutomaticAnswer("installationErrorWithRetry", QMessageBox.Retry);
    installer.setMessageBoxAutomaticAnswer("DownloadError", QMessageBox.Retry);
    installer.setMessageBoxAutomaticAnswer("archiveDownloadError", QMessageBox.Retry);
    installer.installationFinished.connect(function() {
        gui.clickButton(buttons.NextButton);
    })
}

Controller.prototype.WelcomePageCallback = function() {
    // click delay here because the next button is initially disabled for ~1 second
    gui.clickButton(buttons.NextButton, 3000);
}

Controller.prototype.CredentialsPageCallback = function() {
    gui.clickButton(buttons.NextButton);
}

Controller.prototype.IntroductionPageCallback = function() {
    gui.clickButton(buttons.NextButton);
}

Controller.prototype.TargetDirectoryPageCallback = function()
{
    //dev is the user in our docker image
    gui.currentPageWidget().TargetDirectoryLineEdit.setText(installer.value("HomeDir") + "/Qt");
    gui.clickButton(buttons.NextButton);
}

Controller.prototype.PerformInstallationPageCallback = function() {
    gui.clickButton(buttons.CommitButton);
}

Controller.prototype.ComponentSelectionPageCallback = function() {
    function list_packages() {
      var components = installer.components();
      console.log("Available components: " + components.length);
      var packages = ["Packages: "];
      for (var i = 0 ; i < components.length ;i++) {
          packages.push(components[i].name);
      }
      console.log(packages.join(" "));
    }

    list_packages();

    var widget = gui.currentPageWidget();

    console.log(widget);

    widget.deselectAll();
    widget.selectComponent("qt.qt5.5130");
    widget.selectComponent("qt.qt5.5130.gcc_64");
    // widget.deselectComponent("");
   
    gui.clickButton(buttons.NextButton);
}

Controller.prototype.LicenseAgreementPageCallback = function() {
    gui.currentPageWidget().AcceptLicenseRadioButton.setChecked(true);
    gui.clickButton(buttons.NextButton);
}

Controller.prototype.StartMenuDirectoryPageCallback = function() {
    gui.clickButton(buttons.NextButton);
}

Controller.prototype.ReadyForInstallationPageCallback = function()
{
    gui.clickButton(buttons.NextButton);
}

Controller.prototype.FinishedPageCallback = function() {
    var checkBoxForm = gui.currentPageWidget().LaunchQtCreatorCheckBoxForm;
    if (checkBoxForm && checkBoxForm.launchQtCreatorCheckBox) {
        checkBoxForm.launchQtCreatorCheckBox.checked = false;
    }
    gui.clickButton(buttons.FinishButton);
}

run with verbose so you don't have to wait too much time without output

qt.run -platform minimal --verbose --script ./qt-installer-noninteractive.qs 

Solution 6 - Qt

Take a look at this awesome project: aqtinstall https://github.com/miurahr/aqtinstall/

It can install Qt on Linux, Mac and Windows machines without any interaction.

There's also a Github action that uses this tool: https://github.com/jurplel/install-qt-action

Solution 7 - Qt

Credentials are now mandatory since 3.2.1, as explained a bit above. A qtaccount.ini file is created in ~/.local/share/qt. If you can't save & reuse this file, because your script needs to work for multiple users for example, you can use this new CredentialsPageCallback:

Controller.prototype.CredentialsPageCallback = function() {
  var page = gui.pageWidgetByObjectName("CredentialsPage");
  page.loginWidget.EmailLineEdit.setText("MYEMAIL");
  page.loginWidget.PasswordLineEdit.setText("MYPASSWORD");
  gui.clickButton(buttons.NextButton);
}

As always, please be careful when moving passwords around, especially in clear text.

Solution 8 - Qt

The Qt installer v4.0 has been released, and it can run headless now:

qt-unified-windows.exe install --root C:\Qt\InstallFolder

You can use --help for a list of available commands:

qt-unified-windows.exe --help

The command-line installer requires user interaction, but this can be bypassed with flags. See this wiki page for a full list.

You can download the installer here.

Solution 9 - Qt

I had the same problem and came up with a simple python script that basically does the same what the official Qt installer does. You can find it here.

And that's how to use it:

sudo apt install python3-requests p7zip-full wget

wget https://git.kaidan.im/lnj/qli-installer/raw/master/qli-installer.py
chmod +x qli-installer.py

./qli-installer.py 5.11.3 linux desktop

Then the Qt installation can be found at ./5.11.3/gcc_64/ in this case. With other systems/targets (i.e. mac ios or linux android android_armv7) this will differ of course.

https://lnj.gitlab.io/post/qli-installer/

Solution 10 - Qt

This works for me!

 export DISPLAY=:1
 Xvfb :1 -screen 0 1024x768x16 &
 fluxbox &
 x11vnc -display :1 &

Connect to server using any vnc client

Solution 11 - Qt

Note: the script which is described below has been deprecated in the meantime. Rationale and some alternative scripts are listed on the project's home page. Perhaps some of its forks do work, however.

Couple of months ago, I have crafted a configurable helper script for Qt installation automation. Although it is not a truly headless installer, as it simply iterates through install wizard screens, it can be used in continuous integration servers, and in fact it is tested this way.

Notes & features:

  • Works on Linux, MacOS, and Windows.
  • Qt version, components, and install path are configurable.
  • Always uses the most recent online installer.
  • Tested in Travis CI.
  • Bash is required, but it is typically present on continuous integration servers (at least on Travis).
  • Public domain (via CC0 waiver).

Home page: https://github.com/skalee/non-interactive-qt-installer

Solution 12 - Qt

It's necessary to write in credentials in order to pass through credentials menu. In order to avoid that it's necessary to run docker build command with following network argument:

docker build --network none -t <img_name> <Dockerfile_path>

It was something that was missing in order to succesfully run qt interactive installation in docker.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAntoineView Question on Stackoverflow
Solution 1 - QtnocnokneoView Answer on Stackoverflow
Solution 2 - QtNilView Answer on Stackoverflow
Solution 3 - QtJoshua WadeView Answer on Stackoverflow
Solution 4 - QtbenlauView Answer on Stackoverflow
Solution 5 - QtPPPView Answer on Stackoverflow
Solution 6 - QtAndrey SemakinView Answer on Stackoverflow
Solution 7 - QtKriegalexView Answer on Stackoverflow
Solution 8 - QtJoshua WadeView Answer on Stackoverflow
Solution 9 - QtLNJView Answer on Stackoverflow
Solution 10 - QtJarosław OśkaView Answer on Stackoverflow
Solution 11 - QtskaleeView Answer on Stackoverflow
Solution 12 - QtFilip ZorićView Answer on Stackoverflow