Systemd Example for a Simple Ruby Daemon Supervision | COMMENTS Since the new ubuntu versions migrated from upstart to systemd in order to unify basic Linux service behaviors across all distributions we now have to deal with systemd as a default service manager/supervisor. In this article I will describe basics of how to write your first service on this platform.
Services directory location:
1 /lib/systemd/system/*.service Logs location:
1 /var/log/syslog It’s even more convinient to fetch them with a special journalctl utility which reads a systemd journal:
1 $ journalctl --since "2017-02-25 00:00:00" Now let’s create a simple Ruby script which will run an infinite loop:
1 2 $ cd /home/username/ $ vim mydaemon.rb 1 2 3 4 5 6 $stdout.reopen('/home/username/mydaemon.log', 'a') $stdout.sync = true loop.with_index do |_, i| puts i sleep(3) end And start it as a daemon:
1 2 $ ruby mydaemon.rb & [1] pid Checking logs to make sure the daemon is running as expected:
1 2 3 4 5 6 $ tail -f mydaemon.log 0 1 2 3 ^C And stop it:
1 $ kill pid It’s time to add a systemd service which will start this daemon automatically and restart it whenever it was stopped or crashed.
1 2 3 4 5 6 7 8 9 10 11 $ vim /lib/systemd/system/mydaemon.service
[Unit] Description=Simple supervisor
[Service] User=username Group=username WorkingDirectory=/home/username Restart=always ExecStart=/usr/bin/ruby mydaemon.rb In contrary to upstart systemd does not start new services automatically. You can check it’s status with:
1 2 3 4 $ systemctl status mydaemon ● mydaemon.service - Simple supervisor Loaded: loaded (/lib/systemd/system/mydaemon.service; static; vendor preset: enabled) Active: inactive (dead) And start it with:
1 $ systemctl start mydaemon Now status should show mydaemon.rb was started and running with a pid assigned
1 2 3 4 5 6 7 8 9 10 $ systemctl status mydaemon ● mydaemon.service - Simple supervisor Loaded: loaded (/lib/systemd/system/mydaemon.service; static; vendor preset: enabled) Active: active (running) since date Main PID: pid (ruby) Tasks: 2 Memory: 4.0M CPU: 52ms CGroup: /system.slice/mydaemon.service └─pid /usr/bin/ruby mydaemon.rb If you now try to kill the process - supervisor should immediately restart it:
1 2 3 4 5 6 7 8 9 10 11 $ kill pid $ systemctl status mydaemon ● mydaemon.service - Simple supervisor Loaded: loaded (/lib/systemd/system/mydaemon.service; static; vendor preset: enabled) Active: active (running) since date Main PID: new_pid (ruby) Tasks: 2 Memory: 4.0M CPU: 49ms CGroup: /system.slice/mydaemon.service └─new_pid /usr/bin/ruby mydaemon.rb Helpful resources:
Systemd man Systemd for upstart users
Bigger systemd service example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 [Unit] Description=My description here
After=another.target After=some.service
[Service] Type=simple # forking/oneshot/dbus/notify/idle
PIDFile=/absolute/file/name
User=username Group=groupname
WorkingDirectory=/home/username/some/dir
Restart=on-failure
Environment=ONE='one' "TWO='two two' too" THREE= EnvironmentFile=/path/to/file/with/variables
ExecStartPre=/run/some/command ExecStartPre=/run/some/other/command ExecStart=/usr/bin/node /opt/webhook/server.js ExecStartPost=/lastly/run/this
[Install] WantedBy=multi-user.target Restart options:
Upstart <-> Systemd commands cheatsheet: