3

I want to migrate gammu-smsd service to mariadb, so I have edited service systemctl edit --full gammu-smsd.service - I have added mariadb.service on After line.

[Unit]
Description=SMS daemon for Gammu
Documentation=man:gammu-smsd(1)
After=mariadb.service postgresql.service network-online.target

Checked that mariadb exists: systemctl list-units --type=service:

mariadb.service loaded active running MariaDB 10.3.15 database server

But I do not see new dependency anywhere:

systemctl list-dependencies gammu-smsd.service 
gammu-smsd.service
● ├─system.slice
● └─sysinit.target
●   ├─dev-hugepages.mount
●   ├─dev-mqueue.mount
●   ├─fake-hwclock.service
●   ├─keyboard-setup.service
●   ├─kmod-static-nodes.service
●   ├─proc-sys-fs-binfmt_misc.automount
●   ├─resolvconf.service
●   ├─sys-fs-fuse-connections.mount
●   ├─sys-kernel-config.mount
●   ├─sys-kernel-debug.mount
●   ├─systemd-ask-password-console.path
●   ├─systemd-binfmt.service
●   ├─systemd-hwdb-update.service
●   ├─systemd-journal-flush.service
●   ├─systemd-journald.service
●   ├─systemd-machine-id-commit.service
●   ├─systemd-modules-load.service
●   ├─systemd-random-seed.service
●   ├─systemd-sysctl.service
●   ├─systemd-sysusers.service
●   ├─systemd-tmpfiles-setup-dev.service
●   ├─systemd-tmpfiles-setup.service
●   ├─systemd-udev-trigger.service
●   ├─systemd-udevd.service
●   ├─systemd-update-utmp.service
●   ├─cryptsetup.target
●   ├─local-fs.target
●   │ ├─-.mount
●   │ ├─boot.mount
●   │ ├─DietPi.mount
●   │ ├─systemd-fsck-root.service
●   │ ├─systemd-remount-fs.service
●   │ ├─tmp.mount
●   │ └─var-log.mount
●   └─swap.target
●     └─var-swap.swap

Also, gammu-smsd starts before maria DB is ready. Can anybody point what I am doing wrong? Thanks!

2 Answers 2

0

After= only ensures that the service starts after the other service, if both services are activated.

If you want to have a real dependency to mariadb you have to use Requires= or Wants=. This defines the following behavior:

  • if you activate gammu-smsd, mariadb will also get activated
  • if gammu-smsd is starting and mariadb isn't running, it will be started for you
  • if mariadb gets stopped and gammu-smsd is running, it will be stopped for you

Usually you will still want to use After=, because Require= and Wants= don't ensure order. If you only use Requires= or Wants= gammu-smsd may be started in parallel or before mariadb.

If you use Require= and After= gammu-smsd won't get started if mariadb fails to start. Where asWants= still will get gammu-smsd started, if mariadb fails to start. The author of the gammu-smsd RPM probably put the After for both mariadb and postgresql there, so that you can choose between one, both or none of them by activating the appropriate services.

In practice you don't necessarily need to add the Requires= or Wants= line to the gammu-smsd configuration. Just make sure that mariadb is activated.

Your problem is probably, that mariadb successfully entered the running state but still isn't ready to accept connections. At least on RHEL mariadb is configured as Type=simple that means it immediately enters the running state as soon as the mariadb process is started, even though it isn't accepting connections yet.

One simple and hacky way to deal with that would be to simply add a short delay to the start of gammu-smsd with:

ExecStartPre=/bin/sleep 30

A more advanced way would be to use something like this: https://github.com/vishnubob/wait-for-it.

For more information you should read the man pages for systemd.unit and systemd.service.

Type=

Configures the process start-up type for this service unit. One of simple, exec, forking, oneshot, dbus, notify or idle:

If set to simple (the default if ExecStart= is specified but neither Type= nor BusName= are), the service manager will consider the unit started immediately after the main service process has been forked off. It is expected that the process configured with ExecStart= is the main process of the service. In this mode, if the process offers functionality to other processes on the system, its communication channels should be installed before the service is started up (e.g. sockets set up by systemd, via socket activation), as the service manager will immediately proceed starting follow-up units, right after creating the main service process, and before executing the service's binary. Note that this means systemctl start command lines for simple services will report success even if the service's binary cannot be invoked successfully (for example because the selected User= doesn't exist, or the service binary is missing).

Requires=

Configures requirement dependencies on other units. If this unit gets activated, the units listed here will be activated as well. If one of the other units fails to activate, and an ordering dependency After= on the failing unit is set, this unit will not be started. Besides, with or without specifying After=, this unit will be stopped if one of the other units is explicitly stopped. This option may be specified more than once or multiple space-separated units may be specified in one option in which case requirement dependencies for all listed names will be created. Note that requirement dependencies do not influence the order in which services are started or stopped. This has to be configured independently with the After= or Before= options. If a unit foo.service requires a unit bar.service as configured with Requires= and no ordering is configured with After= or Before=, then both units will be started simultaneously and without any delay between them if foo.service is activated. Often, it is a better choice to use Wants= instead of Requires= in order to achieve a system that is more robust when dealing with failing services.

Note that this dependency type does not imply that the other unit always has to be in active state when this unit is running. Specifically: failing condition checks (such as ConditionPathExists=, ConditionPathIsSymbolicLink=, … — see below) do not cause the start job of a unit with a Requires= dependency on it to fail. Also, some unit types may deactivate on their own (for example, a service process may decide to exit cleanly, or a device may be unplugged by the user), which is not propagated to units having a Requires= dependency. Use the BindsTo= dependency type together with After= to ensure that a unit may never be in active state without a specific other unit also in active state (see below).

Note that dependencies of this type may also be configured outside of the unit configuration file by adding a symlink to a .requires/ directory accompanying the unit file. For details, see above.

Wants=

A weaker version of Requires=. Units listed in this option will be started if the configuring unit is. However, if the listed units fail to start or cannot be added to the transaction, this has no impact on the validity of the transaction as a whole. This is the recommended way to hook start-up of one unit to the start-up of another unit.

Note that dependencies of this type may also be configured outside of the unit configuration file by adding symlinks to a .wants/ directory accompanying the unit file. For details, see above.

Before=, After=

These two settings expect a space-separated list of unit names. They configure ordering dependencies between units. If a unit foo.service contains a setting Before=bar.service and both units are being started, bar.service's start-up is delayed until foo.service has finished starting up. Note that this setting is independent of and orthogonal to the requirement dependencies as configured by Requires=, Wants= or BindsTo=. It is a common pattern to include a unit name in both the After= and Requires= options, in which case the unit listed will be started before the unit that is configured with these options. This option may be specified more than once, in which case ordering dependencies for all listed names are created. After= is the inverse of Before=, i.e. while After= ensures that the configured unit is started after the listed unit finished starting up, Before= ensures the opposite, that the configured unit is fully started up before the listed unit is started. Note that when two units with an ordering dependency between them are shut down, the inverse of the start-up order is applied. i.e. if a unit is configured with After= on another unit, the former is stopped before the latter if both are shut down. Given two units with any ordering dependency between them, if one unit is shut down and the other is started up, the shutdown is ordered before the start-up. It doesn't matter if the ordering dependency is After= or Before=, in this case. It also doesn't matter which of the two is shut down, as long as one is shut down and the other is started up. The shutdown is ordered before the start-up in all cases. If two units have no ordering dependencies between them, they are shut down or started up simultaneously, and no ordering takes place. It depends on the unit type when precisely a unit has finished starting up. Most importantly, for service units start-up is considered completed for the purpose of Before=/After= when all its configured start-up commands have been invoked and they either failed or reported start-up success.

ExecStartPre=, ExecStartPost=

Additional commands that are executed before or after the command in ExecStart=, respectively. Syntax is the same as for ExecStart=, except that multiple command lines are allowed and the commands are executed one after the other, serially.

If any of those commands (not prefixed with "-") fail, the rest are not executed and the unit is considered failed.

ExecStart= commands are only run after all ExecStartPre= commands that were not prefixed with a "-" exit successfully.

ExecStartPost= commands are only run after the commands specified in ExecStart= have been invoked successfully, as determined by Type= (i.e. the process has been started for Type=simple or Type=idle, the last ExecStart= process exited successfully for Type=oneshot, the initial process exited successfully for Type=forking, "READY=1" is sent for Type=notify, or the BusName= has been taken for Type=dbus).

Note that ExecStartPre= may not be used to start long-running processes. All processes forked off by processes invoked via ExecStartPre= will be killed before the next service process is run.

Note that if any of the commands specified in ExecStartPre=, ExecStart=, or ExecStartPost= fail (and are not prefixed with "-", see above) or time out before the service is fully up, execution continues with commands specified in ExecStopPost=, the commands in ExecStop= are skipped.

4
  • Thanks for great answer. It is funny that I already came to ExecStartPre with sleep. But at the end - if anyone interested - the correct answer is Requires + After.
    – Tom HANAX
    Aug 31, 2019 at 18:26
  • You shouldn't necessarily need to have Requires + After, if you have once executed systemctl enable mariadbwhich registers mariadb to autostart. Then having After=mariadb.service should suffice. Assuming mariadb starts properly. It won't show up if you execute systemctl list-dependencies gammu-smsd.service though, but it should keep mariadb running and start gammu-smsd after mariadb.
    – Gellweiler
    Aug 31, 2019 at 19:52
  • Hmm, but as I wrote in question, using only After didn't work. Also using After is in fact setting some kind of dependency, so one could expect that it will show in list-dependencies. So why not?
    – Tom HANAX
    Sep 2, 2019 at 5:48
  • After doesn't mean that the gammu-smsd depends on postgresql and mysql, it just means if you have a postgresql service activated (set to autostostart) then start gammu-smsd after postgresql and the same of mysql. But it doesn't meant that it needs postgresql and mysql to run. Assuming that you want your services to run 24/7 After+Wants=mysql.service has in essance the same effect as only After + "symstemctl enable mysqld". Are you sure that you had mysqld enabled? Anyway I'm glad it's working for you now.
    – Gellweiler
    Sep 2, 2019 at 8:19
1

You should add --after option to see the dependency. In this case your command will look like this:

systemctl list-dependencies --after gammu-smsd.service

You must log in to answer this question.

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