How to Fix “Default-Start Contains No Runlevels” Error When Enabling SysV Init Scripts in Systemd


1 views

When transitioning from Upstart to systemd on Ubuntu 16.10, you might encounter this error while trying to enable a legacy SysV init script:

mydaemon.service is not a native service, redirecting to systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable mydaemon
update-rc.d: error: mydaemonDefault-Start contains no runlevels, aborting.

The error occurs because systemd's compatibility layer (systemd-sysv-install) expects traditional SysV init scripts to declare runlevels in their LSB headers, but finds none. This is particularly common when:

  • Converting between init systems (Upstart → systemd)
  • Creating custom init scripts without proper LSB headers
  • Using scripts originally designed for Upstart

Here's how to properly convert your service:

### /etc/init.d/mydaemon ###
#!/bin/sh
### BEGIN INIT INFO
# Provides:          mydaemon
# Required-Start:    $local_fs $network $named $time
# Required-Stop:     $local_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: My Custom Daemon
# Description:       My long service description
### END INIT INFO

case "$1" in
    start)
        /usr/bin/mydaemon --start
        ;;
    stop)
        /usr/bin/mydaemon --stop
        ;;
    restart)
        /usr/bin/mydaemon --restart
        ;;
    *)
        echo "Usage: $0 {start|stop|restart}"
        exit 1
        ;;
esac

exit 0
  1. Make the script executable:
    chmod +x /etc/init.d/mydaemon
  2. Update the dependency information:
    insserv mydaemon
  3. Register with systemd:
    systemctl daemon-reload
    systemctl enable mydaemon

For better integration, consider creating a native systemd unit file:

### /etc/systemd/system/mydaemon.service ###
[Unit]
Description=My Custom Daemon
After=network.target

[Service]
ExecStart=/usr/bin/mydaemon --start
ExecStop=/usr/bin/mydaemon --stop
Type=forking
Restart=on-failure

[Install]
WantedBy=multi-user.target

Then enable it with:

systemctl daemon-reload
systemctl enable mydaemon.service
  • Verify LSB headers with: lsb_release -a
  • Check script syntax: bash -n /etc/init.d/mydaemon
  • Test manual start: service mydaemon start

When dealing with service management on Ubuntu 16.10 (which uses systemd), you might encounter this error while trying to enable legacy SysVinit scripts. The system still maintains backward compatibility through systemd-sysv-install, but requires proper metadata in the init script.

The key message reveals what's happening:

mydaemon.service is not a native service, redirecting to systemd-sysv-install
Executing: /lib/systemd/systemd-sysv-install enable mydaemon
update-rc.d: error: mydaemon Default-Start contains no runlevels, aborting.

Systemd detects your /etc/init.d/mydaemon as a SysVinit script and delegates to the compatibility layer, which then fails because your script lacks required LSB headers.

For systemd to properly handle SysVinit scripts, they must include Linux Standard Base metadata. Here's a minimal working example:

#!/bin/sh
### BEGIN INIT INFO
# Provides:          mydaemon
# Required-Start:    $local_fs $network $named $time $syslog
# Required-Stop:     $local_fs $network $named $time $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Description:       My custom service
### END INIT INFO

case "$1" in
  start)
    echo "Starting mydaemon"
    /usr/bin/mydaemon
    ;;
  stop)
    echo "Stopping mydaemon"
    killall mydaemon
    ;;
  *)
    echo "Usage: /etc/init.d/mydaemon {start|stop}"
    exit 1
    ;;
esac

exit 0

While fixing the LSB headers works, consider these better approaches:

  1. Convert to native systemd unit (recommended):
    Create /etc/systemd/system/mydaemon.service:
[Unit]
Description=My Custom Daemon
After=network.target

[Service]
ExecStart=/usr/bin/mydaemon
Restart=on-failure
User=root

[Install]
WantedBy=multi-user.target
  1. Use systemd generator:
    For complex SysVinit scripts, create a wrapper:
# /etc/systemd/system/mydaemon.service
[Unit]
Description=Wrapper for mydaemon SysVinit script

[Service]
Type=forking
ExecStart=/etc/init.d/mydaemon start
ExecStop=/etc/init.d/mydaemon stop

[Install]
WantedBy=multi-user.target

After making changes:

# Reload systemd
sudo systemctl daemon-reload

# Enable the service
sudo systemctl enable mydaemon

# Check status
sudo systemctl status mydaemon

Remember that Ubuntu 16.10 is quite old - consider upgrading to a supported release with more mature systemd integration.