在 ubuntu 服务器上静默安装 Qt 运行安装程序
Posted
技术标签:
【中文标题】在 ubuntu 服务器上静默安装 Qt 运行安装程序【英文标题】:Silent install Qt run installer on ubuntu server 【发布时间】:2014-09-26 03:14:40 【问题描述】:我想知道是否有办法在 Ubuntu Server 上静默安装 Qt 运行安装程序? 我的意思是绕过安装程序的选项并进行默认安装?
【问题讨论】:
你不能从存储库安装 Qt 库吗?为什么需要在服务器上运行 Qt 安装程序? 因为运行安装程序提供了二进制文件,所以 Qt 已经为生产做好了准备。 @Pavel Strakhov 是否可以在 docker 容器中安装 qt 库并构建源代码?我尝试在 docker 中运行 QT 安装程序,但没有成功。Network error: [ QNetworkReply::NetworkError(UnknownNetworkError) ] "Failed to connect to server. Check your network connection and try again."
Qt 安装程序的4.0
版本现在对此具有一流的支持。请参阅this answer 了解更多信息。
到目前为止,这里的每个答案都已过时。使用这个installer.exe --root "C:\MyInstallation" --accept-licenses --default-answer install componentA
doc.qt.io/qtinstallerframework/…
【参考方案1】:
从安装程序4.X
开始,您不再需要使用 JS 文件了。 Qt 在线安装程序的4.0
版本对无头安装具有一流的支持。请参阅this answer 了解更多信息。
从安装程序3.0.2-online
29-11-2017 开始,您必须在 JS 脚本中添加延迟,因为“欢迎”页面中的“下一步”按钮被禁用一秒钟左右。
Controller.prototype.WelcomePageCallback = function()
gui.clickButton(buttons.NextButton, 3000);
这一次,他们在3.2.1-online
29-01-2020 release page 上解释了如何跳过新表单
Controller.prototype.ObligationsPageCallback = function()
var page = gui.pageWidgetByObjectName("ObligationsPage");
page.obligationsAgreement.setChecked(true);
page.completeChanged();
gui.clickButton(buttons.NextButton);
有些人可能想知道如何创建神秘的qtaccount.ini
文件(自3.2.1-2-online
起是必需的)。 Qt 只告诉我们应该放在~/.local/share/Qt/
中。我无法找到任何其他信息。当您首次输入凭据时,安装程序会自行创建此文件。因此,只需进行手动安装并在帐户表单后退出。生成的文件看起来像
[General]
email=my.email@domain.ca
pass=mypass
[QtAccount]
email=my.email@domain.ca
jwt=a long hash
u=a small hash
【讨论】:
你成就了我的一天! 是的,有一个跳过按钮,但不会有anymore。Installation of Qt binaries will require a Qt Account
解决办法是创建一个账号或者不使用Qt。
有什么方法可以找到 Controller.ABC... 填充帐户凭据的样子?由于凭证现在是强制性的?我不能只复制我自己的 ini 文件,因为我需要创建一个通用脚本。
@Kriegalex 是的,它叫做Controller.prototype.CredentialsPageCallback
。查看其他答案以了解如何使用它。您的用户名和密码将自动填写为qtaccount.ini
。
@Nil 正如我所说,我不能使用复制的 ini 文件,因为我的脚本应该适用于无头环境中的多个用户(因为它曾经在此凭据成为强制性之前工作)。我需要一种方法让 CredentialsPageCallback 从输入的电子邮件/密码中自动填充信息。此页面上的 CredentialsPageCallback 都只是“下一步”操作。【参考方案2】:
Qt安装程序v4.0
已经发布,现在可以无头运行了:
qt-unified-windows.exe install --root C:\Qt\InstallFolder
您可以使用--help
获取可用命令的列表:
qt-unified-windows.exe --help
命令行安装程序需要用户交互,但这可以通过标志绕过。有关完整列表,请参阅 this wiki page。
您可以下载安装程序here。
【讨论】:
你知道是否有办法不安装示例和文档吗?它们被自动添加,因为它们被视为依赖项。我尝试了--nf
和--nd
,但它们仍然安装。【参考方案3】:
2020 年更新:现在有更好的方法。
Qt 在线安装程序4.0
版本对无头安装具有一流的支持。
请参阅this answer below 了解更多信息。
原答案:
绕过“用户数据收集”屏幕
自 2019 年 10 月 8 日起,在 Windows 上添加了一个额外的屏幕,这将导致安装挂起。您可以在.qs
文件中添加以下内容来单击它:
Controller.prototype.DynamicTelemetryPluginFormCallback = function()
var widget = gui.currentPageWidget();
widget.TelemetryPluginForm.statisticGroupBox.disableStatisticRadioButton.checked = true;
gui.clickButton(buttons.NextButton);
选择“存档”和“最新版本”
最近的另一个变化是包类别。 LTS 现在是唯一默认选择的,这意味着您必须先在包类别中选择“最新版本”才能安装最新的 Qt 版本。
这是如何做到这一点的:
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();
// ...
有关 Windows 的更完整示例,请参阅 here。
【讨论】:
您是如何找到按钮的名称和路径的? TelemetryPluginForm.statisticGroupBox.disableStatisticRadioButtongui.currentPageWidget()
似乎还给了一个 JS 对象。幸运的是,我在获取小部件后能够做到这一点:console.log(JSON.stringify(widget));
。我也在使用--verbose
,但我认为在这种情况下不会有什么不同。【参考方案4】:
注意:下面描述的脚本在此期间已被弃用。项目的home page 中列出了基本原理和一些替代脚本。不过,也许它的一些forks 确实有效。
几个月前,我为 Qt 安装自动化制作了一个可配置的帮助脚本。虽然它不是一个真正的无头安装程序,因为它只是通过安装向导屏幕进行迭代,它可以在持续集成服务器中使用,实际上它是通过这种方式进行测试的。
注意事项和功能:
适用于 Linux、MacOS 和 Windows。 Qt 版本、组件和安装路径是可配置的。 始终使用最新的在线安装程序。 在 Travis CI 中测试。 Bash 是必需的,但它通常存在于持续集成服务器上(至少在 Travis 上)。 公共领域(通过 CC0 豁免)。首页:https://github.com/skalee/non-interactive-qt-installer
【讨论】:
【参考方案5】:看看这个很棒的项目:aqtinstall
https://github.com/miurahr/aqtinstall/
它可以在Linux、Mac和Windows机器上安装Qt,无需任何交互。
还有一个使用此工具的 Github 操作:https://github.com/jurplel/install-qt-action
【讨论】:
这个。尝试了这两种方法后,我可以说使用aqtinstall
比维护QtIFW
脚本更容易,也更容易造成挫败感。【参考方案6】:
自 3.2.1 起,凭据现在是强制性的,如上文所述。在~/.local/share/qt
中创建一个qtaccount.ini 文件。如果您无法保存和重用此文件,例如因为您的脚本需要为多个用户工作,您可以使用这个新的 CredentialsPageCallback:
Controller.prototype.CredentialsPageCallback = function()
var page = gui.pageWidgetByObjectName("CredentialsPage");
page.loginWidget.EmailLineEdit.setText("MYEMAIL");
page.loginWidget.PasswordLineEdit.setText("MYPASSWORD");
gui.clickButton(buttons.NextButton);
与往常一样,在移动密码时请小心,尤其是明文。
【讨论】:
【参考方案7】:必须输入凭据才能通过凭据菜单。 为了避免需要使用以下网络参数运行 docker build 命令:
docker build --network none -t <img_name> <Dockerfile_path>
这是为了在 docker 中成功运行 qt 交互式安装而缺少的东西。
【讨论】:
【参考方案8】:上面的脚本是旧的。这应该可以工作(我添加了重试下载错误)
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);
详细运行,这样您就不必等待太多时间而没有输出
qt.run -platform minimal --verbose --script ./qt-installer-noninteractive.qs
【讨论】:
在 Windows 上,您可能会收到一条错误消息,指出 Visual C++ Redistributable 安装程序失败。如果已经安装了 VC++,可能会发生这种情况,并且可以通过将installationError
/ installationErrorWithRetry
的自动答案设置为 QMessageBox.Ignore
而不是 QMessageBox.Retry
来修复。
如果您的脚本适用于旧版本,则应将组件选择保留为:widget.selectComponent("qt.VERSION.gcc_64");
widget.selectComponent("qt.qt5.VERSION.gcc_64");
【参考方案9】:
这对我有用!
export DISPLAY=:1
Xvfb :1 -screen 0 1024x768x16 &
fluxbox &
x11vnc -display :1 &
使用任何 vnc 客户端连接到服务器
【讨论】:
通常情况下,xvfb-run --auto-servernum <command-to-run>
会更好。【参考方案10】:
我遇到了同样的问题,并想出了一个简单的 python 脚本,它与官方 Qt 安装程序的功能基本相同。你可以找到它here。
这就是它的使用方法:
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
在这种情况下,可以在./5.11.3/gcc_64/
找到 Qt 安装。对于其他系统/目标(即mac ios
或linux android android_armv7
),这当然会有所不同。
https://lnj.gitlab.io/post/qli-installer/
【讨论】:
https://git.kaidan.im
似乎从今天开始关闭。
是的,对不起。有git.sr.ht/~lnj/qli-installer,但如果你使用它的 aqtinstall fork 可能是最好的:github.com/miurahr/aqtinstall【参考方案11】:
Qt 工具包是使用 Qt 安装程序框架 (QtIFW) 打包的。 QtIFW 安装程序支持--script
选项,允许您通过Controller Scripting API 以编程方式控制安装。这是以非交互方式安装 Qt 5 的 qt-installer-noninteractive.qs
文件:
// 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);
此脚本演示如何选择/取消选择某些组件。根据您的需要进行自定义,或者完全删除这些行以进行默认安装。同样,您可能想要自定义或删除TargetDirectoryLineEdit
行。像这样运行 Qt 安装程序:
qt-opensource-linux-x64-5.5.1.run --script qt-installer-noninteractive.qs
添加-platform minimal
进行无头安装。未来基于 QtIFW 较新版本的安装程序应该能够改用--silent
选项(请参阅QTIFW-166)。
添加--verbose
以获得更详细的控制台输出(有助于收集组件名称、向导页面名称等)。 This link 也有助于找出组件名称。
【讨论】:
-platform minimum 不适用于 qt-opensource-linux-x64-5.6.0.run 使用qt-opensource-linux-x64-android-5.7.0.run
,-platform minimal
失败,Unknown option: p, l, a, t, f, o, r, m
,--platform minimal
失败,Unknown option: platform
和 --silent
失败,Unknown option: silent
加上QXcbConnection: Could not connect to display
和Aborted (core dumped)
没有系统用户界面。
Unknown option: p, l, a, t, f, o, r, m
消息打印不正确(这是一个错误)。命令仍然成功。
设法完成静默安装,但在 qs
文件中稍作更改以使用包罗万象的 widget.selectAll();
。
如果您想知道组件名称的来源,它似乎来自这里:github.com/qtproject/qtsdk/tree/master/packaging-tools/…【参考方案12】:
在回答不同类型的 Qt 版本的向导问题时,几乎没有什么细微的不同。为了让它更简单,我打包了一个通用脚本来从离线/在线安装程序中提取 Qt。
脚本: qtci/extract-qt-installer at master · benlau/qtci
示例用法:
extract-qt-installer qt-opensource-linux-x64-android-5.5.1.run ~/Qt
环境变量”
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")
此外,它很少有脚本可以下载和安装不同版本的 Qt。
qtci/recipes at master · benlau/qtci
【讨论】:
以上是关于在 ubuntu 服务器上静默安装 Qt 运行安装程序的主要内容,如果未能解决你的问题,请参考以下文章
在 Ubuntu 14.04 上安装 Qt 5.5.1 - 在终端上抛出 qt.network.ssl 错误