Commit 41fd71911e1f6209369d87523b993c5cdceaacf6
1 parent
02844e59
Added Readme
Showing
4 changed files
with
149 additions
and
1 deletions
README.md
| 1 | -# DaemonBase Library | |
| 2 | 1 | \ No newline at end of file |
| 2 | +# DaemonBase Library | |
| 3 | + | |
| 4 | +Simple C++ header only template for creating Linux daemons | |
| 5 | + | |
| 6 | +### What are daemon services/processes ? | |
| 7 | +A dæmon is a program that runs silently in the background.<br> | |
| 8 | +Commonly, dæmon processes are created to offer a specific service. | |
| 9 | + | |
| 10 | +**Dæmon** processes usually: | |
| 11 | +- Live for a long time; | |
| 12 | +- Started at boot time; | |
| 13 | +- Terminate only during shutdown; | |
| 14 | +- Have no controlling terminal. | |
| 15 | + | |
| 16 | +[//]: # (### Dæmon Characteristics) | |
| 17 | + | |
| 18 | +[//]: # (The previously listed characteristics have certain implications:) | |
| 19 | + | |
| 20 | +[//]: # () | |
| 21 | +[//]: # (- do one thing, and one thing only) | |
| 22 | + | |
| 23 | +[//]: # (- resource leaks eventually surface) | |
| 24 | + | |
| 25 | +[//]: # (- consider current working directory) | |
| 26 | + | |
| 27 | +[//]: # (- no (or only limited) user-interaction possible) | |
| 28 | + | |
| 29 | +[//]: # (- how to create (debugging) output) | |
| 30 | + | |
| 31 | +### Usage | |
| 32 | +DaemonBase has a simple, straightforward api with callbacks to handle your daemon events. | |
| 33 | +```cpp | |
| 34 | +#include "daemonbase.h" | |
| 35 | +#include <cstdlib> | |
| 36 | + | |
| 37 | +using namespace osdev::components::daemon; | |
| 38 | +using namespace std::chrono_literals; | |
| 39 | + | |
| 40 | +class MyExampleDaemon : public DaemonBase | |
| 41 | +{ | |
| 42 | +public: | |
| 43 | + void on_start(const daemonconfig &config) override | |
| 44 | + { | |
| 45 | + /// Called once after daemon starts automatically with system startup | |
| 46 | + /// or when you manually call `$ system,ctl start MyExampleDaemon` | |
| 47 | + | |
| 48 | + /// Initialize your code here... | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + daemonlog::info("MyExampleDaemon::on_start(): MyExampleDaemon version: " + config.get("version") + " started successfully!"); | |
| 53 | + } | |
| 54 | + | |
| 55 | + void on_update() override | |
| 56 | + { | |
| 57 | + /// Called every DURATION set in set_update_duration()... | |
| 58 | + | |
| 59 | + /// Update your code here | |
| 60 | + | |
| 61 | + daemonlog::info("MyExampleDaemon::on_update()"); | |
| 62 | + } | |
| 63 | + | |
| 64 | + void on_stop() override | |
| 65 | + { | |
| 66 | + /// Called once before daemon is about to exit with system shutdown or when you manually call `$ systemctl stop MyExampleDaemon` | |
| 67 | + /// Cleanup your code here... | |
| 68 | + | |
| 69 | + daemonlog::info("MyExampleDaemon::on_stop()"); | |
| 70 | + } | |
| 71 | + | |
| 72 | + void on_reload(const daemonconfig &cfg) override | |
| 73 | + { | |
| 74 | + /// Called once after your daemon's config fil is updated then reloaded with `$ systemctl reload MyExampleDaemon` | |
| 75 | + /// Handle your config updates here... | |
| 76 | + | |
| 77 | + daemonlog::info("MyExampleDaemon::on_reload(): new daemon version from updated config: " + cfg.get("version")); | |
| 78 | + } | |
| 79 | +}; | |
| 80 | + | |
| 81 | + | |
| 82 | +int main(int argc, char *argv[]) | |
| 83 | +{ | |
| 84 | + MyExampleDaemon oDaemon; // Create the daemon instance. | |
| 85 | + | |
| 86 | + oDaemon.set_name("MyAweSomeExampleDaemon"); // Set daemon name to identify logs in syslog | |
| 87 | + oDaemon.set_update_duration(3s); // Set duration to sleep before triggering the on_update callback 3 seconds. | |
| 88 | + oDaemon.set_cwd("/root"); // set daemon's current working directory to roots home-folder | |
| 89 | + oDaemon.run(argc, argv); // run the daemon | |
| 90 | + | |
| 91 | + return(EXIT_SUCCESS); // Close the main process now the child process is running. | |
| 92 | +} | |
| 93 | +``` | |
| 3 | 94 | \ No newline at end of file | ... | ... |
systemd/MyExampleDaemon.conf
0 → 100644
systemd/MyExampleDaemon.service
0 → 100644
| 1 | +# Properties docs: https://www.freedesktop.org/software/systemd/man/systemd.service.html | |
| 2 | +[Unit] | |
| 3 | +Description=@PROJECT_DESCRIPTION@ | |
| 4 | +After=network.target | |
| 5 | + | |
| 6 | +[Service] | |
| 7 | +Type=forking | |
| 8 | +ExecStart=/usr/bin/@PROJECT_NAME@ --config /etc/@PROJECT_NAME@/@PROJECT_NAME@.conf | |
| 9 | +ExecReload=/bin/kill -s SIGHUP $MAINPID | |
| 10 | +ExecStop=/bin/kill -s SIGTERM $MAINPID | |
| 11 | +User=root | |
| 12 | +SyslogIdentifier=@PROJECT_NAME@ | |
| 13 | + | |
| 14 | +[Install] | |
| 15 | +WantedBy=multi-user.target | |
| 0 | 16 | \ No newline at end of file | ... | ... |
systemd/README.md
0 → 100644
| 1 | +Linux systems that use systemd for managing services, .service files are typically placed in the /lib/systemd/system/ directory or the /etc/systemd/system/ directory. The .conf files may be placed in a similar directory, such as /etc/MyExampleDaemon/. | |
| 2 | + | |
| 3 | +### .service | |
| 4 | +```ini | |
| 5 | +# Properties docs: https://www.freedesktop.org/software/systemd/man/systemd.service.html | |
| 6 | +[Unit] | |
| 7 | +Description=Simple C++ template example for creating Linux daemons | |
| 8 | +After=network.target | |
| 9 | + | |
| 10 | +[Service] | |
| 11 | +# Configures the process start-up type for this service unit. One of simple, exec, forking, oneshot, dbus, notify or idle. | |
| 12 | +# https://unix.stackexchange.com/questions/733890/systemd-service-unit-restart-on-failure-doesnt-restart-daemon | |
| 13 | +Type=forking | |
| 14 | +# when systemctl start is called | |
| 15 | +ExecStart=/usr/bin/MyExampleDaemon --config /etc/MyExampleDaemon/MyExampleDaemon.conf | |
| 16 | +# when systemctl reload MyExampleDaemon (for reloading of the service's configuration) it will trigger SIGHUP | |
| 17 | +# which will be caught by signal_handler and trigger the on_reload callback. | |
| 18 | +ExecReload=/bin/kill -s SIGHUP $MAINPID | |
| 19 | +# when systemctl stop MyExampleDaemon called: Will trigger SIGTERM which will be caught by signal_handler | |
| 20 | +# and trigger the on_stop callback. | |
| 21 | +ExecStop=/bin/kill -s SIGTERM $MAINPID | |
| 22 | +User=root | |
| 23 | +StandardError=syslog | |
| 24 | +SyslogIdentifier=MyExampleDaemon | |
| 25 | + | |
| 26 | +[Install] | |
| 27 | +# Start after boot | |
| 28 | +WantedBy=multi-user.target | |
| 29 | +``` | |
| 30 | + | |
| 31 | + | |
| 32 | +### .conf | |
| 33 | +```ini | |
| 34 | +# here you can have your daemon configuration | |
| 35 | +name=MyExampleDaemon | |
| 36 | +version=0.0.1 | |
| 37 | +description=Simple C++ template example for creating Linux daemons | |
| 38 | +``` | ... | ... |