Evgenii Legotckoi
15 лютого 2016 р. 21:07

Qt Linux - Урок 001. Автозапуск програми Qt під Linux

Поговоримо, про те, як додати в Qt програму функціонал з налаштування автозапуску даної програми. Наприклад, у нас є вікно налаштувань і хочемо зробити можливість налаштування автозапуску програми з цього діалогового вікна.

На відміну від автозапуску у Windows , де можна скористатися QSettings та внести зміни в реєстр, в Linux потрібно створити спеціальний файл, який буде відповідати за автозапуск програми при вході користувача в операційну систему.

Допустимо назву проекту і відповідно назва виконуваного файлу буде AutorunLinux, тоді потрібно буде створити файл AutorunLinux.desktop наступним шляхом:

  1. ~/.config/autostart/AutorunLinux.desktop

Вміст файлу, що виконується, потрібно зробити аналогічним іншим файлам автозапуску інших програм, щоб гарантовано отримати необхідний результат. У випадку з Ubuntu Linux 15.04/15.10 вміст файлу вийшов так:

  1. [Desktop Entry]
  2. Type=Application
  3. Exec=/home/dekadent/QT/Projects/build-AutorunLinux-Desktop_Qt_5_5_1_GCC_64bit-Debug/AutorunLinux
  4. Hidden=false
  5. NoDisplay=false
  6. X-GNOME-Autostart-enabled=true
  7. Name[en_GB]=AutorunLinux
  8. Name=AutorunLinux
  9. Comment[en_GB]=AutorunLinux
  10. Comment=AutorunLinux

Де параметр Exec вказує шлях до файлу програми, що виконується.

Також не забудьте зробити файл виконуваним:

  1. chmod +x ~/.config/autostart/AutorunLinux.desktop

Для того, щоб гарантовано бути впевненим у правильності підготовлюваного вмісту файлу автозапуску, рекомендую для початку додати додаток до автозапуску за допомогою стандартної утиліти Startup Applications .

Ця утиліта створить гарантовано робочий варіант файлу для вашої програми. Після чого Вам залишиться тільки додати вміст через програмний код з автоматичною модифікацією шляху до файлу програми, що виконується.

Структура проекта

Для демонстрації програмного коду пропоную створити наступний проект, з таким вмістом:

  • AutorunLinux.pro - профайл проекту;
  • widget.h - заголовний файл головного вікна програми;
  • widget.cpp - файл вихідних кодів головного вікна програми;
  • widget.ui - форма головного вікна програми;
  • main.cpp - основний файл вихідних кодів програми.

У цьому додатку буде чекбокс, за станом якого ми видалятимемо і додаватимемо програми в автозапуск при натисканні кнопки PushButton. При запуску програми буде вискакувати повідомлення, що програма запущена. Зовнішній вигляд програми:

віджет.h

У заголовному файлі з усіх змін буде лише оголошення слота для натискання кнопки:

  1. #ifndef WIDGET_H
  2. #define WIDGET_H
  3.  
  4. #include <QWidget>
  5.  
  6. namespace Ui {
  7. class Widget;
  8. }
  9.  
  10. class Widget : public QWidget
  11. {
  12. Q_OBJECT
  13.  
  14. public:
  15. explicit Widget(QWidget *parent = 0);
  16. ~Widget();
  17.  
  18. private slots:
  19. void on_pushButton_clicked();
  20.  
  21. private:
  22. Ui::Widget *ui;
  23. };
  24.  
  25. #endif // WIDGET_H

widget.cpp

  1. #include "widget.h"
  2. #include "ui_widget.h"
  3. #include <QMessageBox>
  4. #include <QDir>
  5. #include <QFile>
  6. #include <QTextStream>
  7. #include <QStandardPaths>
  8.  
  9. Widget::Widget(QWidget *parent) :
  10. QWidget(parent),
  11. ui(new Ui::Widget)
  12. {
  13. ui->setupUi(this);
  14. QMessageBox::information(this,"AutoRun","Apllication is started!");
  15. }
  16.  
  17. Widget::~Widget()
  18. {
  19. delete ui;
  20. }
  21.  
  22. void Widget::on_pushButton_clicked()
  23. {
  24. // Путь к папке автозапуска
  25. QString autostartPath = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation).at(0) + QLatin1String("/autostart");
  26. /* Проверяем, существует ли директория, в которой будет храниться файл автозапуска.
  27. * А то мало ли... пользователь удалил...
  28. * */
  29. QDir autorunDir(autostartPath);
  30. if(!autorunDir.exists()){
  31. // Если не существует, то создаём
  32. autorunDir.mkpath(autostartPath);
  33. }
  34. QFile autorunFile(autostartPath + QLatin1String("/AutorunLinux.desktop"));
  35. /* Проверяем состояние чекбокса, если отмечен, то добавляем приложения в автозапуск.
  36. * В противном случае удаляем
  37. * */
  38. if(ui->checkBox->isChecked()) {
  39. // Далее проверяем наличие самого файла автозапуска
  40. if(!autorunFile.exists()){
  41.  
  42. /* Далее открываем файл и записываем в него необходимые данные
  43. * с указанием пути к исполняемому файлу, с помощью QCoreApplication::applicationFilePath()
  44. * */
  45. if(autorunFile.open(QFile::WriteOnly)){
  46.  
  47. QString autorunContent("[Desktop Entry]\n"
  48. "Type=Application\n"
  49. "Exec=" + QCoreApplication::applicationFilePath() + "\n"
  50. "Hidden=false\n"
  51. "NoDisplay=false\n"
  52. "X-GNOME-Autostart-enabled=true\n"
  53. "Name[en_GB]=AutorunLinux\n"
  54. "Name=AutorunLinux\n"
  55. "Comment[en_GB]=AutorunLinux\n"
  56. "Comment=AutorunLinux\n");
  57. QTextStream outStream(&autorunFile);
  58. outStream << autorunContent;
  59. // Устанавливаем права доступа, в том числе и на исполнение файла, иначе автозапуск не сработает
  60. autorunFile.setPermissions(QFileDevice::ExeUser|QFileDevice::ExeOwner|QFileDevice::ExeOther|QFileDevice::ExeGroup|
  61. QFileDevice::WriteUser|QFileDevice::ReadUser);
  62. autorunFile.close();
  63. }
  64. }
  65. } else {
  66. // Удаляем файл автозапуска
  67. if(autorunFile.exists()) autorunFile.remove();
  68. }
  69. }

Підсумок

В результаті роботи даного коду програма вноситиме себе в автозапуск і запускатиметься при вході користувача в систему. Для перевірки працездатності, створіть за допомогою програми файл автозапуску, вийдіть із системи та увійдіть знову (Log Out/ Log In).

Вихідний код проекту: AutorunLinux

Вам це подобається? Поділіться в соціальних мережах!

a
  • 21 вересня 2018 р. 15:08

Спасибо за статью!

Пример рабочий! Со своим проектом тоже получилось!


Наткнулся на эту статью когда решал задачу запуска Qt app с помощью .

Когда пробовал с помощью получилось запустить простой проект Qt с QCoreApplication. Т.е. без gui.

Для этого оказалось достаточно создать файл (в моем случае) в /etc/systemd/system/

[Unit]
Description=qt_console_app service desription

[Service]
ExecStart=/home/user/cpp_examples/build/build_qt_console_app/qt_console_app
Restart=always

[Install]
WantedBy=graphical.target

И запустить:


Но если хочу запускать проект Qt с gui - не получается!

С помощью видно ошибку:

QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-root'
сен 21 11:29:44 debian systemd-demo[11389]: qt.qpa.screen: QXcbConnection: Could not connect to display
сен 21 11:29:44 debian systemd-demo[11389]: Could not connect to any X display.

Пытался играться с переменными DISPLAY и с Xauthority. Но воз и ныне там.

Только что на линуксовой форуме прочитал, что не для приложений с gui. Там советуют пользоваться средствами автозапуска. Это, скорее-всего, и есть тема данной статьи, которая сработало.

Не подскажете, может ли есть какой-то путь, хитрости, чтобы, всё-таки, запустить проект Qt с GUI с помощью ?


И второй вопрос. Через пробовал в том числе потому что нужен рестарт приложения, если упадет. Там всего-лишь дописывается одна строчка в вышеприведенный файл.

И с помощью Вашего подхода можно ли как-то дописать авторестарт при падение программы?

Evgenii Legotckoi
  • 21 вересня 2018 р. 15:24

Если я вас правильно понял, то авторестарт сюда дописывается  QString autorunContent.
Не могли бы вы не выделять пока слова жирным текстом, в комментариях сломан парсинг тегов, завтра буду чинить. Поэтому съедаются жирные слова.

a
  • 24 вересня 2018 р. 20:40

Не могли бы подробнее рассказать об этой возможности? Я докопался до запросов Desktop Entry Files + restart, но до сих пор не найду autorunContent, о котором Вы писали...

Evgenii Legotckoi
  • 24 вересня 2018 р. 20:42

Ну я имел ввиду, что дописать в коде вот сюда то, о чём вы говорили про рестарт

  1. QString autorunContent("[Desktop Entry]\n"
  2. "Type=Application\n"
  3. "Exec=" + QCoreApplication::applicationFilePath() + "\n"
  4. "Hidden=false\n"
  5. "NoDisplay=false\n"
  6. "X-GNOME-Autostart-enabled=true\n"
  7. "Name[en_GB]=AutorunLinux\n"
  8. "Name=AutorunLinux\n"
  9. "Comment[en_GB]=AutorunLinux\n"
  10. "Comment=AutorunLinux\n");
a
  • 24 вересня 2018 р. 20:47

Просто сейчас правлю сам файл example.desktop. Пытаюсь понять какую пару key=value мне нужно дописать.

Evgenii Legotckoi
  • 24 вересня 2018 р. 20:55

Если честно, то я не уверен, что это вообще можно реализовать через *.desktop файл. Я сделал предположение на основе того, что вы сказали про *.desktop и рестарт.

Все варианты, которые встречаются на форумах, предполагают наличие демона, который следит за тем, чтобы программа была онлайн.

Например я использую supervisor для автостарта сервисов сайта. Поэтому перезагрузка скриптов сайта у меня делается через killall. Грубовато, но supervisor ещё ни разу не подводил.



a
  • 24 вересня 2018 р. 21:00

Не могли бы дать ссылку на пример? Какое-то рабочее использование. Т.е. у меня есть Qt Gui App, которое я бы хотел запускать при старте системы и в случае, если оно грохнется. Если о чем Вы говорите это поможет сделать, не могли бы просвятить в виде ссылки или примерного направление копания))

Evgenii Legotckoi
  • 24 вересня 2018 р. 21:09

А вот здесь у меня есть пример использования supervisor.

https://evileg.com/ru/post/3/

Вся статья вам там не интересна, интересен только шаг с настройкой supervisor. Он получается будет у вас как зависимость к вашему приложению, но вопрос зависимостей - это уже отдельная тема для разговора. В данном случае к самому программированию supervisor отношения не имеет. Это настройка демона.


a
  • 27 вересня 2018 р. 21:07

Спасибо! На данный момент выбор пал в сторону скрипта с бесконечным циклом, перегружающим программу при падение.

Здесь подробнее описал.

k
  • 09 лютого 2024 р. 05:43

как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up
  • Останні коментарі
  • Evgenii Legotckoi
    16 квітня 2025 р. 17:08
    Благодарю за отзыв. И вам желаю всяческих успехов!
  • IscanderChe
    12 квітня 2025 р. 17:12
    Добрый день. Спасибо Вам за этот проект и отдельно за ответы на форуме, которые мне очень помогли в некоммерческих пет-проектах. Профессиональным программистом я так и не стал, но узнал мно…
  • AK
    01 квітня 2025 р. 11:41
    Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
  • Evgenii Legotckoi
    09 березня 2025 р. 21:02
    К сожалению, я этого подсказать не могу, поскольку у меня нет необходимости в обходе блокировок и т.д. Поэтому я и не задавался решением этой проблемы. Ну выглядит так, что вам действитель…
  • VP
    09 березня 2025 р. 16:14
    Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…