• Stars
    star
    154
  • Rank 242,095 (Top 5 %)
  • Language
    C++
  • License
    BSD 3-Clause "New...
  • Created over 6 years ago
  • Updated about 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A platform independent library to easily create system services and use some of their features

QtService

A platform independent library to easily create system services and use some of their features

Github Actions status Codacy Badge AUR

Looking for a maintainer! If anyone is interested in continuing development of the library, please write me here: #30

Features

  • Allows you to create system (and user) services for various systems
    • Provides a single Interface to implement only once without having to care to much about the platform
    • Actual platform specifc stuff is provided via plugins, making it easy to support other backends as well
    • Most backends support native logging (i.e. journald, syslog, winevents, ...)
    • Supports socket-activation (for systemd & launchd)
    • Interfaces can be used to handle general service events
  • Easy testing/debugging by simply switching the service backend via the start arguments
  • Provides very basic service control to, e.g. get the status of a service or start/stop it
  • Provides generic callbacks to allow realtively easy access to platform specific features
  • Comes with a "Terminal frontend mode" which allows to create a CLI interface that communicates with the actual service without any extra coding needed
    • Terminals will connect to the running service. If none is running, they can start it (on some platforms)
    • Terminals send their command line arguments to the running service
    • A connected terminal can send input to the master (via stdin) and receive output (stdout)
    • Terminals can disconnect by beeing closed, leaving the service running (even the one that started the master)
    • The Service gets a "Terminal" handle for each connected terminal, allowing parallel connections. Each terminal implements QIODevice, making communication easy
    • For all this no extra code is needed from your side
  • Supported service backends:
    • Systemd (For most modern Linux Distros)
    • Windows Services
    • Launchd (Tested on MacOs, but should theoretically work on other unixes as well)
    • Android Services
    • "Standard Services" - A platform independed dummy backend that runs services as a normal proccess - useful for testing, debugging or as fallback.
  • QtCreator template to easily create a service project, with configuration file templates for each platform

Note: What this framework does explicitly not handle is "service installation" - as that is extremly different on all platforms and cannot be easily generalized. Performing the service installation, registration or whatever the platform needs is up to the developer. However, all the files that are needed as metadata for a service on each platform are provided via the QtCreator project template, which makes it significantly easier to deploy your service, as all thats left is to correctly "apply" those.

Details on what exactly is supported by each backend can be found in the doxygen documentation under the "Related Pages" tab.

Download/Installation

  1. Package Managers: The library is available via:
    • Arch-Linux: AUR-Repository: qt5-service
    • MacOs:
      • Tap: brew tap Skycoder42/qt-modules
      • Package: qtservice
      • IMPORTANT: Due to limitations of homebrew, you must run source /usr/local/opt/qtservice/bashrc.sh before you can use the module.
  2. Simply add my repository to your Qt MaintenanceTool (Image-based How-To here: Add custom repository):
    1. Start the MaintenanceTool from the commandline using /path/to/MaintenanceTool --addTempRepository <url> with one of the following urls (GUI-Method is currently broken, see QTIFW-1156) - This must be done every time you start the tool:
    2. A new entry appears under all supported Qt Versions (e.g. Qt > Qt 5.11 > Skycoder42 Qt modules)
    3. You can install either all of my modules, or select the one you need: Qt Service
    4. Continue the setup and thats it! you can now use the module for all of your installed Kits for that Qt Version
  3. Download the compiled modules from the release page. Note: You will have to add the correct ones yourself and may need to adjust some paths to fit your installation! In addition to that, you will have to download the modules this one depends on as well.
  4. Build it yourself! Note: This requires all build an runtime dependencies to be available. If you don't have/need cmake, you can ignore the related warnings. To automatically build and install into your Qt installation, run:
    1. Install and prepare qdep
    2. Download the sources. Either use git clone or download from the releases. If you choose the second option, you have to manually create a folder named .git in the projects root directory, otherwise the build will fail.
    3. qmake
    4. make (If you want the tests/examples/etc. run make all)
    5. Optional step: make doxygen to generate the documentation
    6. make install

Usage

The C++ part of the Service is relatively simple. All you have to do is implement the QtService::Service interface and start it in your main. The most important methods of the service are start and stop - which are called when the service was started or stopped...

class TestService : public QtService::Service
{
	Q_OBJECT

public:
	explicit TestService(int &argc, char **argv) : //the reference here is important!
		Service{argc, argv}
	{}

protected:
	CommandMode onStart() override {
		qDebug() << "Service was started";
		return Synchronous; //service is now assumed started
	}

	CommandMode onStop(int &exitCode) override {
		qDebug() << "Stop received";
		// do some complicated stopping stuff asynchronously that takes some time...
		QTimer::singleShot(3000, this, [this](){
			emit stopped(EXIT_SUCCESS);
		});
		return Asynchronous; // service is still stopping until "stopped" has been emitted
	}
};

int main(int argc, char *argv[]) {
	// IMPORTANT: do NOT create a QCoreApplication here - this is done internally by the backends!
	// also, do nothing else in the main besides setting the serices properties! Any setup etc. must all be
	// done in the onStart method!!!
	TestService service{argc, argv};
	return service.exec();
}

Rules of usage:
You should always follow the following rules when using/creating a service. You can also find this list in the QtService::Service class documentation:

  • Do not create a QCoreApplication yourself - this is done internally
  • Use the same constructor signature to pass the main arguments. It is very important that the argc argument is passed as reference! Passing as value will crash your application
  • Do nothing else in the main besides setting the serices properties that need to be set early! Any setup etc. must all be done in the Service::onStart method!!! (The properties that need to be set early all have a hint in their documentation)
  • Never call QCoreApplication::quit (or QCoreApplication::exit)! Use Service::quit instead
  • Do not rely on QCoreApplication::aboutToQuit, as this may not be emitted at all, or on some arbitrary point. Put all cleanup code in the Service::onStop method
  • Be careful with Service::preStart - only use it when you have no other choice

Actually running the service depends on your choosen backend. When testing with the standard backend, you can simply run the service without any parameters, or the backend explicitly specified:

/path/to/service --backend standard

To run with a system backend, you need to register the executable somehow in the service system of your operating system. The trick here is to register it with the backend as parameter. So for example, on windows you would register the service as \path\to\service --backend windows. For more details check the documentation or create a service project from the template - it will create service files that already do this for you.

Terminals

To allow terminals, you must set the QtService::Service::terminalActive property to true and implement the QtService::Service::terminalConnected and optionally the QtService::Service::verifyCommand methods. The service is started the same way as usual. Internally, you will get the terminals as soon as they have connected and can then process their arguments and communicate with them.

To start a terminal client, simply prepend --terminal as well as the backend the service is running on to the command line. It is recommended to create a small wrapper script for each platform that takes care of these parameters. On linux, for example, you would create a shell script like below that simply starts the executable with the additional parameters:

#!/bin/sh
# use as "service-cli <arguments>" (assuming this script is named service-cli)
exec /path/to/service --backend systemd --terminal "$@"

(The platform argument is recommended to not depend on any windowing system)

Service Control

The QtService::ServiceControl allows you to control services by sending commands to them and retrieving the status. However, what exactly is possible greatly varies for each platform. Always use QtService::ServiceControl::supportFlags to figure out what you can actually do on the current platform. You can also check the doxygen documentation to get an overview over all the backends and their features.

Trouble shooting

Sometimes, a service just won't start, without any apparent reason. This can be very hard to debug, as you cannot debug a service with traditional means. The best tricks I came by this problems are:

  1. Enable as much debugging as possible, by setting the QT_LOGGING_RULES environment variable to qt.service.*.debug=true. This will enable debug logging for the service internals, which might help. To access the system logs, refer to your service managers documentation.
  2. Sometimes, logs are empty or the service crashes before starting. This often indicates, that the service plugins cannot be found. In that case, make sure that:
    1. If you deployed your application, check that the servicebackends plugin folder exists and that the plugin you want to use is in there (for example, qwindows[d].dll for the windows backend).
    2. Check or generate the qt.conf file. It should contain an enty named Plugins that points to the directory that contains the servicebackends folder.
    3. If that still does not help, you can try to manually specify the plugin folder via an environment variable. Simply set QT_PLUGIN_PATH to the directory that contains the servicebackends folder. Use an absolute path if possible.

Important: Some service managers (like windows) do not allow to set environment variables for services from the outside. In such cases, you must set the variables in your main, before loading the service. For example, to set QT_PLUGIN_PATH, you would do:

int main(int argc, char **argv) {
    const auto appDir = QFileInfo{QString::fromUtf8(argv[0])}.dir();
    qputenv("QT_PLUGIN_PATH", appDir.absolutePath().toUtf8());
    
    QtService::Service service{argc, argv};
    return service.exec();
}

Documentation

The documentation is available on github pages. It was created using doxygen. The HTML-documentation and Qt-Help files are shipped together with the module for both the custom repository and the package on the release page. Please note that doxygen docs do not perfectly integrate with QtCreator/QtAssistant.

References

The Service backend code for the windows plugin was created by using the code from https://github.com/qtproject/qt-solutions as a basis.

More Repositories

1

QtAutoUpdater

A Qt library to automatically check for updates and install them
C++
753
star
2

QHotkey

A global shortcut/hotkey for Desktop Qt-Applications
C++
549
star
3

QtMvvm

A mvvm oriented library for Qt, to create Projects for Widgets and Quick in parallel
C++
332
star
4

QtJsonSerializer

A library to perform generic seralization and deserialization of QObjects from and to JSON and CBOR
C++
143
star
5

QtApng

An apng image plugin for Qt to support animated PNGs
C++
102
star
6

QtRestClient

A library for generic JSON-based REST-APIs, with a mechanism to map JSON to Qt objects
C++
88
star
7

QtDataSync

A simple offline-first synchronisation framework, to synchronize data of Qt applications between devices
C++
87
star
8

QtIFW-Advanced-Setup

Create "Qt Installer Framework" installers from your project via qmake
JavaScript
58
star
9

QTaskbarControl

A class to create a taskbar/launcher progress and more, for all desktop platforms
C++
43
star
10

libsodium_dart_bindings

Dart bindings for libsodium, supporting both the VM and JS without flutter dependencies.
Dart
28
star
11

AndroidUtils

Utils for easy c++ and qml integration of common android features
C++
23
star
12

repkg

A tool to manage rebuilding of AUR packages based on their dependencies
C++
19
star
13

QAutoStart

A class to easily register your application as autostart application
C++
19
star
14

qdep

A very basic yet simple to use dependency management tool for qmake based projects
Python
18
star
15

qpmx

A frontend for qpm, to provide source and build caching
C++
16
star
16

QSslServer

An extension of QTcpServer to support ssl. The counterpart to QSslSocket
C++
16
star
17

QuickExtras

Additional Stuff for Qt Quick Controls 2, to make it work event better
QML
14
star
18

KeepassTransfer

A collection of tools to securely transfer passwords to your browser
C++
14
star
19

firebase_auth_rest

A platform independent Dart/Flutter Wrapper for the Firebase Authentication API based on REST
Dart
14
star
20

QSingleInstance

A simple single instance application for Qt
C++
13
star
21

QPluginFactory

A factory class to easily load generic plugins
C++
12
star
22

QPathEdit

A Qt-Widget to get local file and folder-paths in an optimized and simple way
C++
12
star
23

QTinyAes

A Qt-Wrapper for the AES-implementation kokke/tiny-AES128-C
C++
11
star
24

QSettingsDialog

Has been replaced by https://github.com/Skycoder42/QtMvvm
C++
11
star
25

qsshfs

A gui wrapper around sshfs
C++
10
star
26

QtUtils

A collection of various Qt-Classes, branch-sorted
C++
10
star
27

QObjectListModel

A Collection of classes to easily create models with QObject and Q_GADGET classes for widgets and quick
C++
10
star
28

qt-json

A basic package for simple json serialization between json and qt classes
C++
10
star
29

QtBackgroundProcess

A Library to create background applications with simple, automated foreground control
C++
10
star
30

dolphin-seafile-plugin

A plugin for dolphin to show the seafile synchronization status
C++
9
star
31

QConsole

A non-blocking Qt Style console class to easily handle stdin/out/err
C++
9
star
32

dart_pre_commit

A small collection of pre commit hooks to format and lint dart code
Dart
9
star
33

QtModules

A collection of ci and deployment scripts to create and deploy Qt modules with travis/appveyor
Python
8
star
34

Syrem

A simple reminder application for desktop and mobile, with synchronized reminders
C++
8
star
35

action-setup-qt

A Github workflow action to install Qt from their online installer
JavaScript
7
star
36

QUrlValidator

A class that provides a QValidator to validate urls
C++
6
star
37

QSettingsGenerator

A qmake extension to generate a C++ settings wrapper for easier, stringless access
Python
5
star
38

keepassxc-client-library

A C++ library to access the browser-plugin-API of KeePassXC to retrieve or create entries.
C++
5
star
39

DialogMaster

A utility to create optimized dialogs with Qt
C++
4
star
40

QCliParser

An extension of QCommandlineParser to make context based CLIs easier
C++
4
star
41

QtRemoteObjectsSslBackend

A backend for QtRemoteObjects to connect via an encrypted SSL connection
C++
4
star
42

cryptopp-qt

A collection of pro/pri files to build and integrate Crypto++ via qmake
QMake
4
star
43

IconThemeBrowser

A small application to browse Qt icon themes
C++
4
star
44

QCtrlSignals

A library to catch and handle windows and unix signals, in a cross platform manner
C++
4
star
45

AndroidContentDevice

A QIODevice implementation to be able to open "content://" urls on android
C++
4
star
46

etebase-dart

Dart/Flutter bindings for libetebase
Dart
3
star
47

QGenericTree

A generic tree data structure for Qt
C++
3
star
48

QIpcPointer

A smart pointer for Qt to create any type on managed shared memory
C++
3
star
49

ApngProject

A collection of projects, all around making apng available in Qt
C++
3
star
50

AniRem

A tool to passivly check for updates on seasons, for proxer.me
C++
3
star
51

flutter_data_extensions

A collection of packages that extend functionally of flutter_data. Namely firebase, encryption and sync.
Dart
3
star
52

openssl-android

qdep package to compile openssl for android and add it to your app
Prolog
3
star
53

qtrng

Qt Random number generator wrapper around "secure" os RNGS
C++
2
star
54

QPipeDevice

A collection of QIODevice classes used for "piping" things between devices
C++
2
star
55

QtProFileParser

A small library to parse Qt Project Files and provide easy handling of those
C++
2
star
56

PWatcher

C++
1
star
57

ClipboardSync

A small tool for clipboard synchronization
C++
1
star
58

action-dart-release

An action to create a github release from a dart package
TypeScript
1
star
59

action-deploy-qt

A Github workflow action to upload qt modules to a server via sshfs
JavaScript
1
star
60

UniInsert

An application to easily insert unicode characters EVERYWHERE
C++
1
star
61

qt-rest

A basic package for simple, generic, builder-based asynchronous rest calls
C++
1
star
62

MangaConvert

Download and convert mangas from single images to pdf
C++
1
star
63

Conflip

A tool to synchronize settings/configurations across multiple machines
C++
1
star
64

deployment

Meta-Repo containing various scripts and files fo generic deployment
QMake
1
star
65

improved-initiative-interceptor

Dart
1
star
66

settings_builder

A dart builder that generates automatic accessors for reading and writing shared preferences.
Dart
1
star
67

dart_test_tools

Additional tools and helpers for writing dart unit tests
Dart
1
star
68

image_galery

Dart
1
star
69

QtMvvmQuick

Has been replaced by https://github.com/Skycoder42/QtMvvm
C++
1
star
70

paxchange

Simple dart script to passively synchronize installed pacman packages between systems
Dart
1
star
71

QtModules-LTS

Build-Repo to build my Qt modules as LTS independent of the primary modules
Shell
1
star
72

QColorEdit

A simple widget to inline-edit colors
C++
1
star
73

QtMvvmWidgets

Has been replaced by https://github.com/Skycoder42/QtMvvm
C++
1
star
74

QtMvvmSettingsWidgets

Has been replaced by https://github.com/Skycoder42/QtMvvm
C++
1
star
75

QtMvvmCore

Has been replaced by https://github.com/Skycoder42/QtMvvm
C++
1
star
76

QExceptionStream

A wrapper around QDebug that allows you to create exception messages like you would write to QDebug
C++
1
star
77

QXmlCodeGen

A simple python script to generate C++ bindings from an XML Schema definition, with support for bootstrapped Qt
Python
1
star
78

aha-dart

Dart client for the AVM Home Automation HTTP Interface + Login
Dart
1
star