Shell – “Proper” way to run shell script as a daemon

daemondebianlinuxshell-script

I am writing a shell script that I would like to run as a daemon on startup without using external tools like daemontools or daemonize.


Linux Daemon Writing HOWTO

According to the Linux Daemon Writing HOWTO, a proper daemon has the following characteristics:

  • forks from the parent process
  • closes all file descriptors (i.e., stdin, stdout, stderr)
  • opens logs for writing (if configured)
  • changes the working directory to one that is persistent (usually /)
  • resets the file mode mask (umask)
  • creates an unique Session ID (SID)

daemonize Introduction

The daemonize Introduction goes further, stating that a typical daemon also:

  • disassociates from its control terminal (if there is one) and ignores all terminal signals
  • disassociates from its process group
  • handles SIGCLD

How would I do all this in a sh, dash, or bash script with common Linux tools only?

The script should be able to run on as many distros as possible without additional software, although Debian is our primary focus.


NOTE: I know there are plenty of answers on the StackExchange network recommending the use of nohup or setsid, but neither of these methods tackles all of the requirements above.


EDIT: The daemon(7) manpage also gives some pointers, although there seem to be some differences between older-style SysV daemons and newer systemd ones. Since compatibility with a variety of distros is important, please ensure the answer makes clear any differences.


Best Answer

Using systemd you should be able to run a script as a daemon by creating a simple unit. There are a lot of different options you can add but this is about as simple as you can get.

Say you have a script /usr/bin/mydaemon.

#!/bin/sh

while true; do
  date;
  sleep 60;
done

Don't forget to sudo chmod +x /usr/bin/mydaemon.

You create a unit /etc/systemd/system/mydaemon.service.

[Unit]
Description=My daemon

[Service]
ExecStart=/usr/bin/mydaemon
Restart=on-failure

[Install]
WantedBy=multi-user.target 

To start the demon you run

systemctl start mydaemon.service 

To start at boot you enable it

systemctl enable mydaemon.service

If on a systemd based system, which a majority of Linux distributions are today, this isn't really an external tool. The negative would be that it won't work everywhere though.

Related Question