Safely enable, disable and remove SysV init links with update-rc.d
You will finish with the correct System V init links for one service, and a way to check that the result will survive a package upgrade. The examples apply to the update-rc.d installed here from init-system-helpers 1.66ubuntu1.
The route
Jump straight to the step you need, or tick off Done means at the end.
- 1. Check the installed command and service name
- 2. Read the init script header before creating links
- 3. Install the default start and stop links
- 4. Disable existing start links without deleting them
- 5. Create a disabled installation when that is the intended default
- 6. Remove links only as part of removal
- 7. Avoid the package-upgrade trap
Allow about fifteen minutes. You need a shell, the service name, and a service script at /etc/init.d/SERVICE if you are creating links. Creating, disabling, enabling or removing links changes boot-time service behaviour, so use an administrative shell only when you have checked the name and intended runlevels.
Checkpoint
This tool manages links for System V style init scripts. It does not write a systemd unit and it does not replace the service script itself.
1. Check the installed command and service name
First confirm which command will run and record the package version. These are ordinary, read-only checks:
$ command -v update-rc.d
/usr/sbin/update-rc.d
$ dpkg-query -W -f='${Package} ${Version}\n' init-system-helpers
init-system-helpers 1.66ubuntu1
$ update-rc.d --help
usage: update-rc.d [-f] <basename> remove
update-rc.d [-f] <basename> defaults
update-rc.d [-f] <basename> defaults-disabled
update-rc.d <basename> disable|enable [S|2|3|4|5]
Replace SERVICE below with the basename of the script, not its full path. For example, if the script is /etc/init.d/warehouse-api, use warehouse-api. Check that exact path before changing anything:
$ test -f /etc/init.d/SERVICE && echo "script exists"
script exists
$ find /etc/rc*.d -maxdepth 1 -type l -name '[SK][0-9][0-9]SERVICE' -printf '%p -> %l\n'
An empty second command is useful: it means there are no matching links to inspect yet. Do not continue with a guessed service name.
2. Read the init script header before creating links
defaults takes dependency and runlevel information from the LSB comment header in the init script. Inspect that header as the same administrator who will run the change:
$ sed -n '/^### BEGIN INIT INFO/,/^### END INIT INFO/p' /etc/init.d/SERVICE
### BEGIN INIT INFO
# Provides: SERVICE
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Should-Start: $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: example service
### END INIT INFO
The values shown are a shape to compare with your file, not a header to paste blindly. If the header is missing or wrong, fix the package or service definition first. The link generator cannot infer safe dependencies from the service name.
3. Install the default start and stop links
Warning
This changes what the init system can start during runlevel changes. Review the script and header first, then run the command with elevated privileges:
$ sudo update-rc.d SERVICE defaults
The normal result is no output. The command creates links under directories such as /etc/rc2.d/ and /etc/rc6.d/, pointing back to /etc/init.d/SERVICE. The two-digit part controls ordering. The exact numbers come from the dependency and runlevel handling on this host, so inspect rather than assuming a particular value.
A key default prevents accidental customisation loss: if matching S or K links already exist, update-rc.d leaves them alone. That means rerunning defaults is not a general way to repair links after manually editing them.
Checkpoint
Verify the links and their targets:
$ find /etc/rc*.d -maxdepth 1 -type l -name '[SK][0-9][0-9]SERVICE' -printf '%p -> %l\n'
/etc/rc2.d/S##SERVICE -> ../init.d/SERVICE
/etc/rc6.d/K##SERVICE -> ../init.d/SERVICE
The sequence numbers and the complete list vary with the script header and installed init tooling. A symlink pointing at another script, or a link in an unexpected runlevel, needs investigation before you start the service.
4. Disable existing start links without deleting them
To stop a service being started through these SysV links, use disable. This is a state change and normally needs elevated privileges:
$ sudo update-rc.d SERVICE disable
The command renames start links in runlevels S, 2, 3, 4 and 5 into stop links. Its sequence calculation uses 100 - old number, so a start link such as S20SERVICE becomes a stop link with the corresponding calculated number. It does not remove the links or delete the init script.
To limit the operation to one start runlevel, give that runlevel as the final argument:
$ sudo update-rc.d SERVICE disable 2
Verify the result, remembering that host-specific link names are expected:
$ find /etc/rc*.d -maxdepth 1 -type l -name '[SK][0-9][0-9]SERVICE' -printf '%p -> %l\n'
Use enable to undo this particular change:
$ sudo update-rc.d SERVICE enable
It renames stop links back to start links using the inverse sequence calculation. The installed command warns that its disable/enable API is not stable, so do not build a long-lived automation contract around undocumented output or internal numbering.
5. Create a disabled installation when that is the intended default
For a script that should be installed but not started by default, use defaults-disabled:
$ sudo update-rc.d SERVICE defaults-disabled
This creates stop links using dependency information from the LSB header. It is different from removing every link: the package can recognise that the service has been deliberately disabled, and a later package upgrade is less likely to treat it as never configured.
Check the result with the same find command from step 3. If any matching links already existed, the tool's preserve-existing-links rule applies and this command will not overwrite that configuration.
6. Remove links only as part of removal
remove is for a script that has already been deleted, commonly during package purge. It removes matching links but leaves unrelated files alone:
$ sudo rm /etc/init.d/SERVICE
$ sudo update-rc.d SERVICE remove
Warning
Deleting an init script is irreversible unless you have a verified backup or package reinstall path. Do not use this as a synonym for disable. If the script still exists, the command refuses to remove the links. The -f option overrides that safety check:
$ sudo update-rc.d -f SERVICE remove
Use -f only when you have deliberately confirmed that every matching link should go. Recovery is to restore /etc/init.d/SERVICE from the owning package or backup, then recreate links with the correct header and defaults or defaults-disabled.
7. Avoid the package-upgrade trap
Deleting links to disable a service is a common mistake. If no links remain, a package's post-install script may run update-rc.d and install the factory defaults again during an upgrade. Use disable, or install deliberately with defaults-disabled, and record the reason in your system change notes.
These commands manage boot-time links, not every way a service can run. A service may still be started manually, by another supervisor, or by a separate systemd unit. Check the actual service manager and package documentation before treating an empty or disabled link set as proof that no process can start.
Done means
- You checked the installed version and used the service basename.
- The init script exists and its LSB header matches the intended runlevels.
- You inspected links after every state-changing command.
- You used
disablerather than deleting links to keep a service disabled. - You reserved
removeand-ffor deliberate script removal or purge work. - You know how to restore the script and recreate its links if the change needs reversing.