Track Down Wrapped Init Scripts with systemd-sysv-generator
Reload systemd and a service you swore was hand-configured turns out to be a wrapper: systemd-sysv-generator just imported it from /etc/init.d/. This guide shows you how to find that script, read the generated unit it produced, and check the ordering and boot targets it was given. Allow about 10 minutes.
The route
Jump straight to the step you need, or tick off Done means at the end.
You need a shell account that can read the service files; reach for sudo only where a step needs privileged access.
What the generator actually does
- It is a compatibility shim, not a converter. In systemd 255, it reads executable-looking scripts from
/etc/init.d/and builds temporary.servicewrappers when the system manager starts or reloads. The wrapper just calls the original script. - It is on its way out. The component is deprecated upstream. Treat any imported service as migration work waiting to happen, not a reason to add more SysV scripts. A native unit gives you clearer dependencies, logging and lifecycle behaviour.
- It has no options worth touching. systemd calls it itself; its documented synopsis is just its own path:
/usr/lib/systemd/system-generators/systemd-sysv-generator
Do not run that path to start or stop a service. Use systemctl for service operations and let systemd invoke its generators in the background.
1. Find the legacy script
List the script named by the service you are investigating. Replace the placeholder with a real service name; this is a read-only command and does not need elevated privileges.
SERVICE_NAME=example-daemon
ls -l "/etc/init.d/$SERVICE_NAME"
sed -n '1,100p' "/etc/init.d/$SERVICE_NAME"
Look for an LSB header between ### BEGIN INIT INFO and ### END INIT INFO. Fields such as Required-Start, Required-Stop, Should-Start, Default-Start and Default-Stop describe ordering and runlevel intent. A script without useful headers can still be wrapped, but systemd has less to go on when ordering it.
Checkpoint
You should have a real file below /etc/init.d/. If it is missing, you are probably looking at a native unit, or a service name from a different package entirely.
2. Ask systemd which unit is active
Use the service name with a .service suffix. Neither command changes service state:
systemctl status "$SERVICE_NAME.service" --no-pager
systemctl cat "$SERVICE_NAME.service"
- For an imported script,
systemctl catcommonly shows a comment saying the unit was automatically generated, aSourcePath=/etc/init.d/...line, and something likeExecStart=/etc/init.d/example-daemon start. The exactType, timeout and stop command depend on the script and its headers. - If systemd cannot find the unit, check the script name and package installation first. The generator only ever looks in
/etc/init.d/; a script anywhere else is not its problem.
3. Inspect dependencies and boot placement
Ask systemd to show the unit's effective ordering and relationships:
systemctl show "$SERVICE_NAME.service" \
-p FragmentPath -p SourcePath -p Type -p Before -p After \
-p WantedBy --no-pager
Generated units live under /run/systemd/, which is runtime state, not a file you should ever edit directly. The SourcePath points back to the SysV script. If you need to change behaviour, change the package configuration or replace the script with a native unit; edits to the generated file are lost on the next reload or boot.
- LSB facilities get translated. In systemd 255,
$remote_fs,$network,$named,$portmapand$timeare recognised and become dependencies on native systemd targets. The generated unit is also ordered afterbasic.target, because systemd does not support SysV scripts as part of early boot. - Runlevels become targets. Enablement shows up as targets such as
runlevel2.targetandrunlevel5.target. The wrapper is wanted by the targets that match the runlevels the original script was enabled for, which is why a script can exist on disk but never start during a normal boot.
4. Reload after a script or package change
Generators run when the system manager reloads, so after a package changes an init script, tell systemd to catch up. This is an administrative operation and may need elevated privileges:
sudo systemctl daemon-reload
systemctl cat "$SERVICE_NAME.service"
The second command is your verification step. Compare SourcePath, the ExecStart and ExecStop lines, and the ordering from systemctl show. A reload does not, by itself, start, stop or restart the service.
Common traps
- Do not stop or disable a production service just to see how it was generated.
systemctl stop,disableandmaskall change availability or boot behaviour. If you have made a reversible change, restore it with the matchingsystemctl enableorsystemctl unmaskcommand once you have confirmed the unit name. - Do not assume a wrapper that starts cleanly matches the old init system exactly. SysV compatibility is broad but not complete.
Safety boundary
When replacing a script, record its current start order, stop order, environment and dependencies first. Write a native unit with explicit After=, Wants= or Requires= relationships, test it in a maintenance window, and only remove the old script once you have a verified rollback path.
Done means
- Identified the source script below
/etc/init.d/. - Confirmed the wrapper with
systemctl cat, including its source path. - Checked type and ordering with
systemctl show. - Know the generated files are disposable, living under
/run/systemd/. - Have a test and rollback plan for any future replacement.