0

I have a very simple SysVinit service in /etc/rc.d:

#!/bin/bash

PIDFILE="/var/run/test.pid"

status() {
  if [ -f "$PIDFILE" ]; then
    echo 'Service running'
    return 1
  fi
  return 0
}

start() {
  if [ -f "$PIDFILE" ] && kill -0 "$(cat "$PIDFILE")"; then
    echo 'Service already running'
    return 1
  fi
  echo 'Starting...'
  test & echo $! > "$PIDFILE"
  return 0
}

stop() {
  if [ ! -f "$PIDFILE" ] || ! kill -0 "$(cat "$PIDFILE")"; then
    echo 'Service not running'
    return 1
  fi
  echo 'Stopping...'
  kill -15 "$(cat "$PIDFILE")" && rm -f "$PIDFILE"
  return 0
}

case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  status)
    status
    ;;
  restart)
    stop
    start
    ;;
  *)
    echo "Usage: $0 {start|stop|restart}"
    exit 1
esac

When the system starts it starts the service.

But when the system stops, it never calls the stop command. The only reason I can think off is that the system either thinks the service is not running or was not started correctly.

But what are the requirements for that?

  • Do you need to return a special exitcode for the start command?
  • Do I need to create a file in /var/lock/subsys to signal that it is active?
  • Anything else that might cause the system to think the service did not start?
4
  • 1
    Which operating system are you using? If Linux, which distribution and version?
    – telcoM
    Commented Apr 18, 2023 at 6:14
  • @telcoM It's Linux, but on a Synology NAS, so it's proprietary distribution with kernel 4.x. It may well be that this problem relates to their implementation. But I just want to know if the above script should be appropiate for the average Linux distro, so that I can rule out that this behaviour is due to my script.
    – Maestro
    Commented Apr 18, 2023 at 14:52
  • It's good as a generic SysVinit script, but when some distributions started to introduce parallelism in the startup/shutdown process, they added some features. For example, RedHat/Fedora added the requirement to create a file in /var/lock/subsys/<scriptname> when the service is successfully started, to allow the shutdown process to optimize away attempts to shut down services that are either not started in the first place or are already stopped manually. Unfortunately I don't know what distribution the Synology NAS is based on; check existing scripts to see if there is a lock requirement?
    – telcoM
    Commented Apr 18, 2023 at 17:48
  • It was once based on Debian but it is so heavily customized by now that it's more of a distribution by itself. With a seperate package system, etc. I tried /var/lock/subsys but it made no difference. Also there are no existing scripts installed, it only uses that directory for user scripts. Maybe they just simulate init.d to stay compatible with custom user scripts made for previous releases, because I cannot find any trace on the filesystem that init.d actually exist. Maybe they just iterate the folder, and call each script during boot by other means.
    – Maestro
    Commented Apr 18, 2023 at 18:52

1 Answer 1

1

It looks like Synology moved from classic SysVinit to upstart in DSM 6 or so, and then to systemd in DSM 7. Both init systems provide backward compatibility for classic SysVinit-style start/stop scripts, but there are some quirks you should be aware of.

If you have DSM 7.0 or newer, then after installing the script you probably should run systemctl daemon-reload, so systemd-sysv-generator should automatically create a .service file for it (maybe in /run/systemd). Then you can start your script with systemctl start <script name> - and in fact should do just that, instead of just running the script manually. systemd will be aware of the need to run <your script> stop job only if it has actually executed the corresponding start job.

This is because systemd will set up each service as a separate control group of processes as it starts them up (and the administrator running the start script manually doesn't do that).

This is something that is completely invisible to the services themselves (unless they specifically go looking for it), and any child processes of the services will inherit this control group membership. If a control group has no processes left in it, it will cease to exist automatically.

When shutting down, systemd will just go through the existing control groups and will run the stop command for any non-default control group it finds. Any services that have been started without using systemctl start will be part of the "administrator's interactive session" control group rather than the "service X" control group, and will essentially be just killed without running the corresponding stop script.

If you need features like an automatic restart for your service if it dies for some reason, you should consider using the appropriate "native" configuration method for the applicable init system:

  • /etc/init/* files for Upstart in Synology DSM 6.x series
  • /etc/systemd/system/*.service files for systemd in Synology DSM 7.x series and newer. These init systems have built-in automatic restart features you can use with just a little bit of configuration, rather than having to write a wrapper script to watch your service process yourself.

Developer Guide for Synology DSM 7

Developer Guide for Synology DSM 6

Possibly helpful notes on configuring services for DSM 6 and 7

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .