Comment by simoncion

1 day ago

To pile on, a minimal OpenRC service file is just as complicated as a minimal SystemD service file; that is, they're both almost-exclusively composed of key-value pairs. For instance, this is the service file for the 'rsyncd' service [0]:

  #!/sbin/openrc-run
  
  command="/usr/bin/rsync"
  command_args="--daemon ${RSYNC_OPTS}"
  pidfile="/var/run/${SVCNAME}.pid"
  
  depend() {
   use net
  }

Like SystemD, OpenRC provides pre/post start/stop hooks that you can use to call out to other programs.

Unlike SystemD if you need to make nontrivial decisions at service-status-management time, you have the option of putting your scripts or calls to other programs inline, rather than hoping that SystemD gives you the hooks you need in the places you need them and passes in the data you require. [1]

[0] And if 'rsyncd' was supervised with 'supervise-daemon', you wouldn't need to specify the location of the pidfile.

[1] As a trivial example, you can dynamically depend on other services depending on system configuration (as PostgreSQL does). As a less-trivial example, you can check for and warn the administrator about common service misconfigurations with the same mechanism that provides service startup and status information (as several services do).

> As a trivial example, you can dynamically depend on other services depending on system configuration (as PostgreSQL does)

Depending on what you want to do, a generator might be appropriate:

> Their main purpose is to convert configuration and execution context parameters that are not native to the service manager into dynamically generated unit files, symlinks or unit file drop-ins

  • Well, here are the relevant parts of the service file:

      get_config() {
          [ -f "${PGDATA%/}/postgresql.conf" ] || return 1
      
          eval echo $(sed -e 's:#.*::' "${PGDATA%/}/postgresql.conf" \
              | awk '$1 == "'$1'" { print ($2 == "=" ? $3 : $2) }')
      }
      
      depend() {
          use net
          provide postgresql
      
          if [ "$(get_config log_destination)" = "syslog" ]; then
              use logger
          fi
      }
    

    If PostgreSQL has been configured, this reads its config file, looks to see if it's configured to use 'syslog' as its log destination, and -if so- adds a dependency on the 'logger' "meta-service". [0]

    What would this look like with a systemd service file generator?

    [0] What's a "meta-service"? 'provide postgresql' makes the service started by this service file provide the 'postgresql' "meta-service". This is useful for PostgreSQL because you can install multiple versions of the software simultaneously... so the service files are named like postgresql-17, and postgresql-18. The 'logger' "meta-service" is useful because who cares which syslog software you have installed... you only care that it speaks syslog.

    • Yeah parsing config files with regular expressions that may or may not properly handle quoting or line continuations etc is… not a great idea in my opinion.

      But of course in this particular case, because systemd makes the /dev/log journal/syslog socket a dependency of every unit by default, there is no need to encode this dependency at all.

      Anyway if you really wanted to you could write this script as a generator and have it put a drop-in in /run/systemd/system/postgres.service.d. But… why?

      3 replies →