Commit 41fd71911e1f6209369d87523b993c5cdceaacf6
1 parent
02844e59
Added Readme
Showing
4 changed files
with
149 additions
and
1 deletions
README.md
| 1 | -# DaemonBase Library | ||
| 2 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | \ No newline at end of file | 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 | +``` |