I've created a shell script daemon, based on the code of this answer. I've written a systemd service file with the following contents:

Description=My Daemon

ExecReload=/bin/kill -1 -- $MAINPID
ExecStop=/bin/kill -- $MAINPID


Just before the while loop starts, I'm creating a PID file (it is going to be created by the daemon, not by the child, or the parent, because they don't come to this point): echo $$ > /run/daemon.pid;. It works fine, but each time I call systemctl status daemon.service, I get the following warning:

daemon.service: PID file /run/daemon.pid not readable (yet?) after start: No such file or directory

If I insert the PID creaton statement echo $$ > /run/daemon.pid; at the very beginning of the script (which will be used by the children and parent, too), I get the following warning:

daemon.service: PID 30631 read from file /run/daemon.pid does not exist or is a zombie.

What would be the best approach for creating the PID file without getting any warning messages by systemd?

2 Answers 2


So the problem you're seeing here is because when Type=forking is in use, then the pid file must be created (with the correct pid) before the parent process exits.

If you create the pidfile from the child, then it will race with the exit of the parent and in some (many?) cases will cause the first error you're seeing.

If you create the pidfile writing $$ to it before you start the child, then it will have the pid of the parent, which will have exited, so you'll see the other error.

One way to do this correctly is to write the pidfile from the parent, just before exiting. In that case, write $! (and not $$), which returns the pid of the last process spawned in background.

For example:


# Run the following code in background:
    while keep_running; do
) &

# Write pid of the child to the pidfile:
echo "$!" >/run/daemon.pid

This should work correctly... HOWEVER, there's a much better way to accomplish this! Read on...

Actually, the whole point of systemd is to daemonize processes and run them in background for you... By trying to do that yourself, you're just preventing systemd from doing it for you. Which is making your life much harder at the same time...

Instead of using Type=forking, simply write your shell script to run in foreground and set up the service to use Type=simple. You don't need any pidfiles then.

Update your /root/bin/daemon.sh to simply do this:


# Run the following code in foreground:
while keep_running; do

(NOTE: Perhaps daemon.sh is not the best name for it at this point... Since that would imply it runs in background. Maybe name it something more appropriate, related to what it actually does.)

Then update the .service file to use Type=simple (which would actually be used by default here, so you could even omit it.)

ExecReload=/bin/kill -1 -- $MAINPID
ExecStop=/bin/kill -- $MAINPID

BTW, you can probably drop ExecStop=, since killing the process with a signal is the default behavior as well...

systemd's Type=forking is really there only for legacy programs that only work that way and can't be easily fixed to work in foreground... It's hacky and inefficient. The whole point of systemd (and some of its alternatives, predecessors) is to do the forking and daemonizing itself and let services just worry about doing what they need to do! :-)

I hope you find this helpful... And I really hope you choose to let systemd do the heavy lifting for you! It's much more efficient that way.

  • one advantage I can see for type=forking is that systemd can know when the service has been started, if there is a potentially slow set-up process before the service is ready type=simple could cause systemd to end up trying to launch other things too soon.
    – Jasen
    Aug 16, 2019 at 2:39
  • 1
    @Jasen But in that case, the best way is to use Type=notify and use the sd-notify protocol to send a ready notification to systemd. Also, if your service is a network server, consider using socket activation, which makes the ready notification a non-issue for the most part, and also prevents clients getting server unreachable errors during a restart of the service.
    – filbranden
    Aug 16, 2019 at 5:41
  • Unfortunately there might be other health-checking services that want to get the PID so they can check on the process. We're only just switching to systemd, and this sort of thing is painful. I don't know a scriptable way to ask systemd for the pid or the status without fragile sed hackery. May 28, 2020 at 19:59
  • Unfortunately, Type=notify is a systemd-specific. Asking application to comply with it ... is asking a bit much. Apr 22 at 17:25

Ok, the error message daemon.service: PID file /run/daemon.pid not readable (yet?) after start: No such file or directory disappeared after I added the following statement to the service file:

ExecStartPost=/bin/sleep 2
  • This solution works a lot better than Type=simple. I am using Type=forking with ISC Bind9 named daemon. Apr 22 at 17:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.