

systemd sysv init compatibility mode is magical. That is in the sense that it tries to handle compatibility with sysv init scripts while you are distracted looking somewhere else.

When it works it works well, but when things break it makes troubleshooting more difficult. Especially if you don't understand what's going on behind the curtain.

The first thing you need to understand is that this probably doesn't do what you expect:

/etc/init.d/sysv-init-script start

In sysv the script would actually be executed. Under systemd the execution is intercepted by LSB here at this line in the script's execution:

. /lib/lsb/init-functions

This eventually invokes /lib/lsb/init-functions.d/40-systemd which redirects the execution of the script so that it is invoked by systemd.

So instead of executing the script what's actually happening is this:

systemctl start sysv-init-script.service

sysv-init-script.service doesn't actually exist so systemd.service handles that as a special case by sort of pretending it does.

From systemd.service(5):

If a service is requested under a certain name but no unit configuration
file is found, systemd looks for a SysV init script by the same name
(with the .service suffix removed) and dynamically creates a service
unit from that script. This is useful for compatibility with SysV. Note
that this compatibility is quite comprehensive but not 100%. For details
about the incompatibilities, see the Incompatibilities with SysV[1]

Long story short, systemd interprets the standard LSB headers in the sysv init script so it execute the sysv init script in the context of something resembling a real systemd service.

Behind the curtain these wrapper service units are generated by /lib/systemd/system-generators/systemd-sysv-generator and you can find the result at /run/systemd/generator.late/ where the wrapper usually looks something like this:

# Automatically generated by systemd-sysv-generator

Description=LSB: A sysV init script systemd-journald-dev-log.socket

ExecStart=/etc/init.d/sysv-init-script start
ExecStop=/etc/init.d/sysv-init-script stop

The problem is that when things break it adds a layer of indirection that makes debugging the sysv init script harder.

To disable systemd redirection do this:


Now executing your /etc/init.d/sysv-init-script directly will work, and so will shell debugging tricks I find really useful such as:

  1. set -ex

    This echos everything the script executes to stdout and terminates the script if any command returns an error (I.e., a non-zero exitcode).

  2. inserting an interactive /bin/bash shell somewhere to "inspect" the environment. This works kind of like setting a breakpoint.

Note however that systemd is pretty neat once you get past the learning curve. Usually it will make more sense to reimplement your sysv init script as a systemd service unit. You can eliminate hundreds of line of complicated error prone shell script with a handful of lines of systemd configuration directives that work better than the original.


John Carver's picture

I have a situation where I need to patch a sysv init script and then get systemd to recognize the change.  The change has been applied to /etc/init.d/lxc, but is not being recognized by 'service restart lxc'.  Apparently the change must also be applied to /usr/lib/x86_64-linux-gnu/lxc/lxc-autostart-helper, which appears to be a verbatim copy of the original /etc/init.d/lxc.

I tried copying the patched sysv init script to overwrite the lxc-autostart-helper and then ran 'systemctl daemon-reload'.  This seemed to work okay, but I doubt it is the proper way to accomplish the task.


Francis Evrard 's picture

when you type "update-rc.d lxc défaults", you should get a "systemd [1] Reload", after which things should be Ok !

Jade's picture

You noted:

But how does one modify the script such that one can change the default "Restart" setting?

I've inherited the SysVinit scripts.  It's now running on a linux OS where systemd is the init system used.  Without having to replace the SysVinit scripts, how can I get it such that these daemons can be restarted if it crashes.  My desire is to set


I'm guessing I need to add somethign to the LSB header???  Any idea on what that is???

Vincent Murphy's picture


I had the same question. I am afraid we are out of luck.

The source code at shows that the generator always uses Restart=no , and doesn't process anything from the LSB header to change this.

Thanks to this very helpful blog post, I will take a copy of the generated service unit from /run/systemd/generated.late and change the Restart there. At least then I know I have not broken anything else in my working service.

Cameron Kerr's picture

Here's the short version, which I just spent an hour or so figuring out (you have to undo some of the defaults). Note that I tested this using Globus's globus-gridftp-server.service (ie. commands such as 'service globus-gridftp-service restart' and script /etc/init.d/globus-gridftp-server).
# /etc/systemd/system/globus-gridftp-server.service.d/override.conf
You'll need to specify the PIDFile, to ensure it picks up the Main PID (you should see a Main PID line in 'systemctl status globus-gridftp-server.service').  In the case of this particular service, the process that it ends up spawning is not, it seems, a traditional daemon process (for some reason it gets started with -no-detach), so I needed to change RemainAfterExit back to the (systemd default) of 'no', whereas the systemd sysv generator default is 'yes'. Otherwise you'll find (though it won't be obvious as to why) that the service will be seen as killed, but won't restart. Enjoy!
Janson's picture

We are planning to move httpd service to a Centos7 machine, in my current Centos6 configuration I have a pre-init script which will be executed before starting apache. The script will accept the user sommand line argument(for ex: serice httpd start) and check the following and execute few things before start the service. I am wondering the same can be done in Centos7 with systemd. Any help will be appeciated. 


[ "$1" == "start" -o "$1" == "restart" -o "$1" == "condrestart" ]

Jeremy Davis's picture

But re SystemD, it sounds like you will want to use the ExecPreStart= directive in your service file. I would assume that would do what you are hoping for?!

The Systemd service doc page is pretty handy IMO.

Assuming that there is an existing service file you wish to update, the correct way to do that is either copy the file (from /lib/systemd/system/...) to /etc/systemd/system/ and edit the copy in /etc (the file in /etc will be used instead of the one in /lib). Or create a file with a path like /etc/systemd/system/MY_SERVICE.service.d/override.conf and include overrides/additions there. IMO the easiest way to do the latter is use the "systemctl edit MY_SERVICE" command.

Alternatively, it's also an option to call an init.d script from a Systemd service file. E.g. stuff like this:

ExecStart=/etc/init.d/MY_SERVICE start
ExecStop=/etc/init.d/MY_SERVICE stop


Add new comment