← Back to context

Comment by simoncion

1 day ago

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?

  • Okay, I'll rephrase the question a bit and ask it again.

    Imagine that you have a service that has a configuration-dependent dependency on rsyslog. For whatever reason, journald's not an option... maybe it's simply not installed, or this service depends on rsyslog-specific behaviors that journald simply doesn't replicate. It doesn't matter why this configuration-dependent dependency exists, it simply exists and there's no workaround.

    Assuming that the rsyslog service is named 'rsyslog', the service with the dependency is named 'stupid-service', the configuration file is named '/etc/stupid-service/stupid-service.conf', and the configuration option to search that config file for is 'logging = syslog', what would the systemd service file generator look like to make 'stupid-service' depend on 'rsyslog' if and only if that config file contains 'logging = syslog'?

    You appear to have worked with these service file generators, which is why I'm asking. I expect you'd know what the generator to accomplish this trivial task would look like, or if it was even possible with generators.

    Also:

    > Yeah parsing config files with regular expressions that may or may not properly handle quoting or line continuations

    Nah, this is substring matching and column-cutting. The only use of regexes ("#.*") is to remove comments. Go check out the format docs for the PostgreSQL config file. [0] It's pretty basic and straightforward.

    [0] <https://www.postgresql.org/docs/17/config-setting.html#CONFI...>

    • Put a script in /etc/systemd/system-generators/ that does something like

        if grep "logging = syslog" /etc/stupid-service/stupid-service.conf >/dev/null; then
          printf "[Unit]\nAfter=rsyslogd.service\n" > "$1/stupid-service.d/10-syslog-dep.conf";
        fi;
      

      > It's pretty basic and straightforward

      Postgres config supports line continuations, so the OpenRC service file you quoted is buggy; it could potentially match a file just because some other option contained a multi-line value that had the string "log_destination = syslog" in it.

      The whole philosophy of systemd is to move away from these kinds of "simple" and "mostly working" pile-of-shell-script systems to actually-unconditionally-correct configuration that doesn't come with bonus text processing surprises.

      1 reply →