{"id":16382727,"url":"https://github.com/baderouaich/daemonpp","last_synced_at":"2025-08-22T09:49:10.415Z","repository":{"id":153536494,"uuid":"629771130","full_name":"baderouaich/daemonpp","owner":"baderouaich","description":"Simple C++ header only template for creating Linux daemons","archived":false,"fork":false,"pushed_at":"2024-10-25T13:14:49.000Z","size":1442,"stargazers_count":19,"open_issues_count":0,"forks_count":6,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-25T03:35:44.771Z","etag":null,"topics":["cmake","cpp","cpp-template","daemon","header-only","linux","single-header","systemd","unix-daemon"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/baderouaich.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-04-19T01:55:56.000Z","updated_at":"2025-01-25T11:52:40.000Z","dependencies_parsed_at":null,"dependency_job_id":"7a7b6aaa-b7f7-419d-9948-e0933867a967","html_url":"https://github.com/baderouaich/daemonpp","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/baderouaich%2Fdaemonpp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/baderouaich%2Fdaemonpp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/baderouaich%2Fdaemonpp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/baderouaich%2Fdaemonpp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/baderouaich","download_url":"https://codeload.github.com/baderouaich/daemonpp/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249333606,"owners_count":21252848,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cmake","cpp","cpp-template","daemon","header-only","linux","single-header","systemd","unix-daemon"],"created_at":"2024-10-11T04:06:11.481Z","updated_at":"2025-04-17T10:34:42.596Z","avatar_url":"https://github.com/baderouaich.png","language":"C++","readme":"## daemonpp\nSimple C++ header only template for creating Linux daemons\n\n### What are daemon services/processes ?\nA dæmon is a program that runs silently in the background.\u003cbr\u003e\nCommonly, dæmon processes are created to offer a specific service.\n\n**Dæmon** processes usually:\n- Live for a long time;\n- Started at boot time;\n- Terminate only during shutdown;\n- Have no controlling terminal.\n\n[//]: # (### Dæmon Characteristics)\n\n[//]: # (The previously listed characteristics have certain implications:)\n\n[//]: # ()\n[//]: # (- do one thing, and one thing only)\n\n[//]: # (- resource leaks eventually surface)\n\n[//]: # (- consider current working directory)\n\n[//]: # (- no \u0026#40;or only limited\u0026#41; user-interaction possible)\n\n[//]: # (- how to create \u0026#40;debugging\u0026#41; output)\n\n### Usage\ndaemonpp has a simple, straightforward api with callbacks to handle your daemon events.\n```cpp\n#include \"daemon.hpp\"\nusing namespace daemonpp;\nusing namespace std::chrono_literals;\n\nclass my_daemon : public daemon\n{\npublic:\n    void on_start(const dconfig\u0026 cfg) override {\n      /// Called once after daemon starts automatically with system startup or when you manually call `$ systemctl start my_daemon`\n      /// Initialize your code here...\n\n      dlog::info(\"my_daemon::on_start(): my_daemon version: \" + cfg.get(\"version\") + \" started successfully!\");\n    }\n\n    void on_update() override {\n      /// Called every DURATION set in set_update_duration()...\n      /// Update your code here...\n\n      dlog::info(\"my_daemon::on_update()\");\n      if(++counter \u003e= 3) { \n          dlog::trace(\"Stopping my_daemon after 3 updates.\");\n          stop(EXIT_SUCCESS);\n      }\n    }\n\n    void on_stop() override {\n      /// Called once before daemon is about to exit with system shutdown or when you manually call `$ systemctl stop my_daemon`\n      /// Cleanup your code here...\n\n      dlog::info(\"my_daemon::on_stop()\");\n    }\n\n    void on_reload(const dconfig\u0026 cfg) override {\n      /// Called once after your daemon's config fil is updated then reloaded with `$ systemctl reload my_daemon`\n      /// Handle your config updates here...\n\n      dlog::info(\"my_daemon::on_reload(): new daemon version from updated config: \" + cfg.get(\"version\"));\n    }\n    \nprivate:\n    int counter = 0;\n};\n\nint main(int argc, const char* argv[]) {\n  my_daemon dmn;                         // create a daemon instance\n  dmn.set_name(\"my_daemon\"); // set daemon name to identify logs in syslog\n  dmn.set_update_duration(3s);   // set duration to sleep before triggering the on_update callback 3 seconds\n  dmn.set_cwd(\"/\");      // set daemon's current working directory to root /\n  dmn.run(argc, argv);                   // run your daemon\n  return EXIT_SUCCESS;\n}\n```\n\n### Examples\nSee [examples](./examples)\n\n## Tutorial - Create a new daemon project in 3 steps\nLet's assume your daemon project is called **my_daemon**\n1. First, clone this repository into a new folder named after your project:\n```bash\ngit clone https://github.com/baderouaich/daemonpp my_daemon\n```\nYour project structure will be like this:\n```text\nmy_daemon\n├── examples/           # example daemon projects to inspire from\n├── include/            # include files contains daemonpp single header files\n├── systemd/            # .service.in and .conf.in files to be configured by cmake\n├── daemonpp.cpp        # daemonpp.cpp sample daemon template\n├── CMakeLists.txt      # CMake project file \n├── LICENSE             # MIT License file\n└── README.md\n```\n\n2. Update your [CMakeLists.txt](CMakeLists.txt) file according to your project properties (name, version and description...)\n```cmake\ncmake_minimum_required(VERSION 3.10)\nproject(my_daemon VERSION \"0.0.1\" DESCRIPTION \"My daemon description\" LANGUAGES CXX)\n          ^                                            ^\n          │_____ update your project name              |\n                                                       |\n                                                       │_____ update your project description\n```\n\n3. Configure your project (to create .service and .conf required daemon files):\n```bash\nmkdir build \u0026\u0026 cd build\ncmake ..\n```\n  \nNow your project structure will look like this:\n```text\nmy_daemon\n├── examples/        \n├── include/        \n├── systemd/        \n├── my_daemon.conf       \n├── my_daemon.service    \n├── my_daemon.cpp       \n├── CMakeLists.txt   \n├── LICENSE\n└── README.md\n```\n\nThat's it! you can now update your daemon code in the my_daemon.cpp file and remove examples/ folder if you don't need.\n\nAlso see how to:\n\n- [Install your daemon](#install-your-daemon)\n\n- [Enable/Disable your daemon to run with system startup](#enabledisable-your-daemon-to-run-with-system-startup)\n\n- [Start/Stop your daemon](#startstop-your-daemon)\n\n- [Restart your daemon](#'estart-your-daemon)\n\n- [Reload your daemon](#install-your-daemon)\n\n- [Uninstall your daemon](#uninstall-your-daemon)\n\n## Install your daemon\n```bash\nsudo make install\n```\n\n## Enable/Disable your daemon to run with system startup\n```bash\nsudo systemctl [enable|disable] my_daemon\n```\n\n## Start/Stop your daemon\nStart\n```bash \nsystemctl start my_daemon\n```\n\u003e will trigger the on_start() callback, providing your config values.\n\nStop\n```bash\nsystemctl stop my_daemon\n``` \n\u003e will trigger the on_stop() callback.\n\n## Restart your daemon\n```bash\nsystemctl restart my_daemon\n```\n\u003e This is equivalent to `sudo systemctl stop your_daemon \u0026\u0026 sudo systemctl start your_daemon`\n\n## Reload your daemon\nif you change  your .service or .conf files, and you reinstalled your daemon, you have to reload \nyour daemon by running:\u003cbr\u003e\n`systemctl reload my_daemon`\n\u003e will trigger the on_reload() callback, providing the new config values.\n\n## Check your daemon's status\n```bash\nsystemctl status my_daemon\n```\n\n## Uninstall your daemon\n1. Stop daemon gracefully\n```bash\nsystemctl stop my_daemon\nsystemctl disable my_daemon\n```\n2. Delete daemon files\n```bash\nsudo make uninstall\n```\nOr\n```bash\nsudo rm -rf /etc/my_daemon/my_daemon.conf /etc/systemd/system/my_daemon.service /usr/bin/my_daemon\n```\n\n## Logging\nUse the built-in **dlog** static class which uses syslog internally. Then you can\nsee your logs by:\n- running `gnome-logs` gui if available.\n- using cat by running `cat /var/log/syslog | grep your_daemon_name`.\n- using tail `tail -f /var/log/syslog` to show all logs or `tail -f /var/log/syslog | grep your_daemon_name`\n- using systemctl status by running `systemctl status your_daemon_name`\n- opening the `/var/log/syslog` file in a text editor and find `your_daemon_name` (not recommended since syslog can be huge).\n\n### TODO\n- [x] re-read configuration file upon SIGHUP\n- [x] relay information via event logging, often done using e.g., syslog(3)\n- [ ] prevent against multiple instances via a lockfile\n- [ ] allow for easy determination of PID via a pidfile\n- [ ] include a system initialization script (for /etc/rc.d/, /etc/init.d/, systemd, …) for other Linux distros such as RedHat 4/5/6 or CentOS that use init scripts instead of systemd\n- [ ] configuration file convention /etc/name.conf\n\n### Features and bugs\nIf you face any problems feel free to open an issue at the [issue tracker][tracker]. If you feel the library is missing a feature, please raise a ticket on Github. Pull request are also welcome.\n\n[tracker]: https://github.com/baderouaich/daemonpp/issues\n\n### References\n- [Jan Schaumann - Advanced Programming in the UNIX Environment Week 10, Segment 1: Dæmon Processes](https://www.youtube.com/watch?v=YbYQqVMv7b8f)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbaderouaich%2Fdaemonpp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbaderouaich%2Fdaemonpp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbaderouaich%2Fdaemonpp/lists"}