Daemonization in Unix programs is probably about restarting programs
utcc.utoronto.ca
utcc.utoronto.ca
And thus, `nohup`.
Quite a few of my self hosted things are spawned using `nohup ./foobar &` and happily run for months at a time.
--
Edit: TIL `daemonize`, I have a new go to!
https://www.freedesktop.org/software/systemd/man/latest/syst...
A random tutorial,
https://medium.com/@benmorel/creating-a-linux-service-with-s...
To normalize machine specs I will run it in a VM on the cloud.
To normalize system environment I run in docker.
I also like to run on Java for code safety and consistency.
So what I have is a VM (Java) running on a VM (Docker) running a VM, running a VM (cloud compute), running on system D. I don't think it's abstracted enough though so I'm looking to find ways to add more VMs to the equation, so as to ensure consistency. Figure if I add a few more VMs, good luck hacking that!
By whom and for what reason? Every non-trivial OS has some form of "daemon" concept, regardless of what name it's given. What alternative is proposed? All I get from this statement is discussion about the deficiencies of how demonization is performed.
[edit] I get it. Don't deamonize yourself. That's fine, and a good idea: it's frequently done wrong and even when it's done right things change and otherwise correct software is suddenly wrong again.
From OpenRC’s docs[0]:
Daemons must not fork. Any daemon that you would like to have monitored by supervise-daemon must not fork. Instead, it must stay in the foreground. If the daemon forks, the supervisor will be unable to monitor it.
If the daemon can be configured to not fork, this should be done in the daemon's configuration file, or by adding a command line option that instructs it not to fork to the command_args_foreground variable shown below.
The “undesired” or “controversial” part is whether programs should do it themselves or not.[0]: https://github.com/OpenRC/openrc/blob/master/supervise-daemo...
It made a lot of sense to me at the time and honestly felt easier. Going back to init.d or upstart just felt like a step backward and so much more complicated that it needed to be. Then SystemdD comes along an have the same expectation and things makes sense again and writing "startup scripts became as easy almost as it was with daemontools.
I don’t recall whether you could tell inetd not to do that.
inetd was (remains?) a perfectly useful solution in this space. It just maybe needs some love to add some convenience features. Off the top of my head: 1) ability to split /etc/inetd.conf into, e.g., /etc/inetd.conf.d; 2) ability to trigger a restart of a specific service, rather than restarting the entirety of inetd.
One, is that HTTP took over the role of a lot of simple servers, thus something like Apache and CGI-BIN was used in place of inetd.
Second, with the rise of interpreted languages (i.e. Perl et al), forking became more expensive. With binary programs, forking tends to be cheap (in a multi-use case) since the executable page are shared across processes. While the interpreter runtime itself is shared (being compiled), the actual script is not (having to be loaded for each instance).
The HTTP servers managed that better (through modules, FastCGI, etc.), so that space didn't really advance under the guise of inetd.
Make no mistake, an inetd service is "fast enough" for a wide array of use cases today, both compiled and interpreted, simply because the hardware is much better today. But, still, when folks think "ad hoc" service today, they're likely turning to HTTP today anyway.
I’d say it’s the modern-day equivalent of daemontools, and it’s under active development.
By everyone and for the reason that service managers lose track of the process, so it increases program complexity for a net negative in usability.
> Every non-trivial OS has some form of "daemon" concept, regardless of what name it's given.
And none of that is relevant, TFA is about the unix self-daemonization pattern, that is what's undesirable.
"Daemonization" is nothing but fork + exec (and exit from the parent)
From the service manager, there should be few distinctions between this and, say, pgsql forking to handle connections. In both cases, I expect all child processes to be tracked.
And please do not tell me the "health check" part : having the main process alive is a broken health check, just like having a server powered-on is a far from enough
If pgsql forks to handle connections, the PPID of the child processes points back to the "main" pgsql process, which is still around.
Whereas, traditionally, if a wannabe daemon forks and exits, the PPID of its now orphaned child reverts to 1.
Setting that on the init process is pointless, since init already has the reaping behavior, and it when a process is reparented it doesn't give init any information about what the parent was when it is reparented.
Setting it on the service process isn't helpful either, since the fored process will get reparented to init after the forking process dies since a dead process can't reap it.
You don't set this on pid 1 because, as you point out, pid 1 is already the reaper of last resort.
You don't set this on the service process either; it is set on a process manager that isn't pid 1, so that process can monitor and collect info about its subtree of processes.
The program that the service manager thinks is starting immediately quits, and it's the grandchild (or even great grandchild) that's actually the payload service.
Because the parent quit, the grandchild becomes reparented to the init daemon; it is not a child of the service manager.
The service manager has no idea what the process ID of the service is.
If the self-daemonizing program writes its PID to a pidfile, and the service manaager is configured to know what that is and look for it, it can be obtained that way.
Not being the parent of the process, the service manager doesn't get notified when that process terminates. It has to use hacks to poll for it; like kill the PID with signal 0 to check liveness, and pray that the PID isn't recycled.
If you're writing a deamon program, make sure daemonization is optional, favoring opt-in over opt-out.
Either you use cgroup (in which case, neither the parent pid nor pidfile nor even the process ID are useful), either you do not (in which case, you leak processes)
Stopping a service means, in the end, killing all processes in the associated cgroup.
This sort of behavior makes writing proper systemd unit files and containers a pain. It is a lot nicer to keep them 'attached' so that you can do things like capture stdout for logging and all that fun stuff.
That is what they are talking about when "daemonizing is considered undesirable".
This belief is mainly because after many years of debugging services, the very first thing I do is run the service outside of the daemon manager, with debugging enabled, so I can strace the process from its beginning.
inetd waited on "all" the sockets; when a connection came in, it started the configured application to deal with it.
daemonization didn't really figure into it, AFAIR.
https://mywiki.wooledge.org/ProcessManagement
Seems reasonable to me. Restarting processes is just something like this:
#!/bin/sh
# service.sh
while :; do
/my/service >> /var/log/service 2>&1
done
service.sh &
The service is just a normal program. If run directly, the inputs and outputs are attached to the terminal. If not, they're redirected to log files. Programs shouldn't care much what their outputs are connected to. Maybe they should turn off terminal escape codes in the outputs if they're not terminals but that's about it.It doesn't handle service dependencies. What if I only want my service to run when I'm on network and VPN is disabled?
And I can think of a lot more. All these things have been implemented in init, or in systemd, for decades.
It was just an example of how simple things can be when programs don't daemonize. Supervising and managing the processes is systemd's job and it does it well. Daemonizing makes its job harder and is not necessary to begin with.
for example I use my WM to start `swww-daemon` and then running `swww <path/to/wallpaper>` just sends a message over a Unix socket to the daemon process which handles everything else. Its sooo much better than internally forking off and all of that, it becomes messy quick and its pretty unnecessary in the present. All that really matters is how robust your IPC and stop-start process is. Sometimes its massively fragile, and it shows.
side note, when I first started Unix I was fascinated with daemons. I still think they are one of the coolest things ever.
I respectfully disagree.
It it fundamentally related to your use-cases, execution times, and design paradigms.
If your team comes from a *nix background, than having dozens of processes interfacing over various pipes/network-sockets/fifo/mem-share is normal. In a cluster environment, having the ability to spin up processes on any host, yet remain functional over middle-ware can be very robust from a maintenance perspective.
A periodic self-restart trigger feature is only a small part of these feature sets.
Containerization on the other hand was necessitated out of poor OS design consistency, and rotten permission handling. It added overhead, complexity, and costs. However, it also solved a very real user requirement of keeping many things operational at the same time.
Daemons are almost certainly still required if you have software that must remain running for >6 months outside a users session. Also, periodic processes do not necessarily have to remain resident in all use cases if that was a concern.
Best of luck, =3
But don't forget that the service managers themselves have to daemonize. :) The programs which they launch don't have to daemonize only because their parent did that already.
A given host assigned capabilities should not require manual intervention, but should allow manual interaction for testing and debugging.
Insisting one method is superior, is often from people that have never hit the terminal spawn limit on a host.
Best of luck, =3
These things still matter when the program is run from a boot script or init daemon, rather than a login session!
Isn't that more the job of `nohup`?
changing the cwd so it doesn't cause problems with mounting/unmounting comes to mind.
There are service managers like systemd and shepherd, which use daemonization under the hood. Then there's container orchestration like docker compose, kubernetes, etc. For my toy servers at home I just use screen and have it set up automatically at boot.
What do you use outside of the microservices camp?
Service managers don't daemonize anything, because they never have to release control to their parent. Just like init always did.
The only thing that's changed with systemd is that inittab now has a dependency management, and richer syntax.