'Writing a unix daemon
I'm trying to code a daemon in Unix. I understand the part how to make a daemon up and running . Now I want the daemon to respond when I type commands in the shell if they are targeted to the daemon.
For example:
Let us assume the daemon name is "mydaemon"
In terminal 1 I type mydaemon xxx. In terminal 2 I type mydaemon yyy.
"mydaemon" should be able to receive the argument "xxx" and "yyy".
Solution 1:[1]
If I interpret your question correctly, then you have to do this as an application-level construct. That is, this is something specific to your program you're going to have to code up yourself.
The approach I would take is to write "mydaemon" with the idea of it being a wrapper: it checks the process table or a pid file to see if a "mydaemon" is already running. If not, then fork/exec your new daemon. If so, then send the arguments to it.
For "send the arguments to it", I would use named pipes, like are explained here: What are named pipes? Essentially, you can think of named pipes as being like "stdin", except they appear as a file to the rest of the system, so you can open them in your running "mydaemon" and check them for inputs.
Finally, it should be noted that all of this check-if-running-send-to-pipe stuff can either be done in your daemon program, using the API of the *nix OS, or it can be done in a script by using e.g. 'ps', 'echo', etc...
Solution 2:[2]
The easiest, most common, and most robust way to do this in Linux is using a systemd socket service.
- Example contents of
/usr/lib/systemd/system/yoursoftware.socket:[Unit] Description=This is a description of your software Before=yoursoftware.service [Socket] ListenStream=/run/yoursoftware.sock Service=yourservicename.service # E.x.: use SocketMode=0666 to give rw access to everyone # E.x.: use SocketMode=0640 to give rw access to root and read-only to SocketGroup SocketMode=0660 SocketUser=root # Use socket group to grant access only to specific processes SocketGroup=root [Install] WantedBy=sockets.target- NOTE: If you are creating a local-user daemon instead of a root daemon, then your systemd files go in
/usr/lib/systemd/user/(seepulseaudio.socketfor example) or~/.config/systemd/user/and your socket is at/run/usr/$(id -u)/yoursoftware.sock(note that you can't actually use command substitution in pathnames in systemd.)
- NOTE: If you are creating a local-user daemon instead of a root daemon, then your systemd files go in
- Example contents of
/lib/systemd/system/yoursoftware.service[Unit] Description=This is a description of your software Requires=yoursoftware.socket [Service] ExecStart=/usr/local/bin/yoursoftware --daemon --yourarg yourvalue KillMode=process Restart=on-failure [Install] WantedBy=multi-user.target Also=yoursoftware.socket - Run
systemctl daemon-reload && systemctl enable yoursoftware.socket yoursoftware.serviceas root- Use
systemctl --user daemon-reload && systemctl --user enable yoursoftware.socket yoursoftware.serviceif you're creating the service to run as a local-user
- Use
- A functional example of the software in C would be way too long, so here's an example in NodeJS. Here is
/usr/local/bin/yoursoftware:#!/usr/bin/env node var SOCKET_PATH = "/run/yoursoftware.sock"; function errorHandle(e) { if (e) console.error(e), process.exit(1); } if (process.argv[0] === "--daemon") { var logFile = require("fs").createWriteStream( "/var/log/yoursoftware.log", {flags: "a"}); require('net').createServer(errorHandle) .listen(SOCKET_PATH, s => s.pipe(logFile)); } else process.stdin.pipe( require('net') .createConnection(SOCKET_PATH, errorHandle) ); - In the example above, you can run many
yoursoftwareinstances at the same time, and the stdin of each of the instances will be piped through to the daemon, which appends all the stuff it receives to a log file.
For non-Linux OSes and distros without systemd, you would use the (typically shell-scripted) startup system to begin your process at boot and the user would receive an error like could not connect to socket /run/yoursoftware.sock when something goes wrong with your daemon.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Community |
| Solution 2 | Jack G |
