Skip to content

Installation on the Raspberry Pi

jbaumann edited this page Dec 11, 2021 · 2 revisions

Prerequisites

User

When installing the System_Watchdog Daemon as a service we let it run as the user pi. Since the daemon might have to execute all manners of commands as the user root, we need to be able to use the command sudo, an elegant solution of Raspbian (and Unix in general) to support the needed privilege elevation

The necessary prerequisite is that the user pi can execute sudowithout entering a password. This is the case in a normal Raspbian installation, but may not be the case in yours. To test it, enter the following command:

sudo ls

If this works without requesting a password, then everything is fine.

If the system requests a password, then we have to reconfigure it to work without that. Check the file /etc/sudoers.d/010_pi-nopasswd. In a default Raspbian installation it should contain the following:

pi ALL=(ALL) NOPASSWD: ALL

Using the command sudo visudo /etc/sudoers.d/010_pi-nopasswd you can change this to:

#pi ALL=(ALL) NOPASSWD: ALL
pi ALL=(ALL) NOPASSWD: /sbin/shutdown

Please be very! careful when editing this file, because if this file contains errors you cannot use sudo anymore.

Python

The daemon is written in Python 3. Python 2 is deprecated and using it no longer makes any sense.

A modern Raspbian installation should have all necessary Python 3 packages, so there should be no need to install additional packages.

Installation as a Daemon

The very short version

Put the daemon files into a directory. The unit file references /opt/system_watchdog, so either use this or change the unit file. Install the unit as a system service, enable and start it. Check logs.

The short version

  1. Download the files in this repository to your Raspberry Pi.
  2. Create a directory /opt/system_watchdog/ as user root sudo mkdir /opt/system_watchdog
  3. Change the owner of this directory to user pi sudo chown pi /opt/system_watchdog
  4. Place everything in the directory /opt/system_watchdog as the user pi.
  5. Change the execution flag of the daemon: chmod +x /opt/system_watchdog/system_watchdog.py
  6. Review the entries in the configuration file system_watchdog.cfg.
  7. Copy, as superuser, the service file to /etc/systemd/system/: sudo cp system_watchdog.service /etc/systemd/system/
  8. Enable the service: sudo systemctl enable system_watchdog
  9. Check the result: sudo systemctl status system_watchdog
  10. Start the service: sudo systemctl start system_watchdog
  11. Check the log for irregularities: journalctl -r -u system_watchdog
  12. Every sleep time seconds the daemon should write a log entry

The long version (or, what is a unit file?)

Writing a daemon today is simple work, all the heavy lifting is done by our trusty systemd (which today is prevalent on most Linux systems).

The unit description

Systemd takes a description file for a service (called a unit) that contains all necessary information for starting, restarting and stopping the service and uses this to guarantee that the service is run according to our wishes.

Our unit file describes a very simple service that should be started very early after booting, but only after e.g., the syslog becomes available. So we start our description of the service with the name, the default dependencies (none), when to start (after the sysinit.target has been reached).

[Unit]
Description=SystemWatchdog Daemon
DefaultDependencies=no
After=multi-user.target
StartLimitIntervalSec=0

The final line is pretty important for our use case. Normally, when a service fails and systemd tries to restart it, it uses start rate limiting to ensure that the system is not overload by it trying to restart a service. But when the rate limit is exceeded, the service is no longer restarted at all. And this behavior can be turned off by setting the value of StartLimitIntervalSec to the value 0.

The service description

The service description contains the specifics of how to start our service. The service type we choose is simple, which means that the service is available simply after starting the executable referenced after ExecStart.

The next step is to define the restart characteristics for our service. We want to restart always (even if the daemon exits without a set return code) and want it to restart after one second pause.

And finally we want the daemon to run as user pi.

[Service]
Type=simple
ExecStart=/opt/system_watchdog/system_watchdog.py
Restart=always
RestartSec=1
User=pi

The installation description

Until now we have described the prerequisites for and the specifics of the service. But until now we do not define that systemd should actually start the service at all. This is done by the last part of our service definition that states that we want the service to be started by the sysinit.target. This is used by systemd when we enable as service to decide when and how to start it.

[Install]
WantedBy=multi-user.target

And this is it. Naturally, systemd offers a lot more flexibility and complexity than shown here, but as shown it can be very simple to define a service with it and thus a system daemon for Linux.

You still need to execute the commands given before, but now it should be clear what happens behind the scenes.