A service remains in the deactivating state when systemd has already started stopping the unit but is still waiting for the ExecStop= command, the main process, or other processes in the control group to exit. To resolve the problem, determine exactly what systemd is waiting for, terminate that process safely, and then configure a stop timeout to prevent the service from hanging again.
Prerequisites and limitations
The commands below apply to systems that use systemd and require root privileges or access through sudo. Replace my.service with the actual unit name. Do not send SIGKILL until you have confirmed that the process is not performing a critical write to a database, file system, or other storage.
The actual stop behavior depends on the unit configuration, including Type=, KillMode=, TimeoutStopSec=, SendSIGKILL=, and any ExecStop= commands. Inspect the effective settings of the installed unit rather than only the file under /etc/systemd/system.
Step 1. Confirm the state and identify the current operation
First, retrieve the service status without paginated output:
sudo systemctl status my.service --no-pager -l
Then query the properties that show the stop phase, processes, and effective timeout:
sudo systemctl show my.service \
-p ActiveState \
-p SubState \
-p Result \
-p MainPID \
-p ControlPID \
-p ExecMainCode \
-p ExecMainStatus \
-p TimeoutStopUSec \
-p KillMode \
-p SendSIGKILL
Interpret the main fields as follows:
ActiveState=deactivatingconfirms that the unit is being stopped.ControlPIDusually identifies the process running the current control command, such asExecStop=.MainPIDcontains the PID of the main process if systemd is still tracking it.TimeoutStopUSecshows the effective stop timeout.KillModedetermines which processes systemd terminates when stopping the unit.
Also inspect the systemd job queue:
sudo systemctl list-jobs
If a stop job is listed for my.service, systemd still considers the stop operation to be in progress. Other pending jobs may explain why related units are also blocked.
Step 2. Inspect the stop logs
Review messages from the service and systemd for the current boot:
sudo journalctl -u my.service -b --no-pager -n 200
To monitor the journal in real time, use:
sudo journalctl -u my.service -f
Look for the following signs:
- a stop command starting without a corresponding completion message;
- messages indicating that the stop timeout was exceeded;
- repeated attempts to close connections or child processes;
- errors accessing sockets, PID files, file systems, or network resources;
- messages such as “process remains running after unit stopped” or similar warnings about processes left in the cgroup.
If the service journal does not contain enough information, filter systemd messages by the unit name:
sudo journalctl -b --no-pager | grep -F 'my.service'
Step 3. Identify the stuck process
Retrieve the PIDs of the main process and the control process:
sudo systemctl show my.service -p MainPID -p ControlPID
For each nonzero PID, inspect the process state:
ps -o pid,ppid,stat,etime,wchan:32,cmd -p PID
Replace PID with the actual number. The STAT column helps identify the nature of the hang:
S— interruptible sleep; the process normally responds to signals.R— running on a CPU.D— uninterruptible kernel sleep, often related to a disk, network file system, driver, or another I/O operation.Z— an exited zombie process that must be reaped by its parent process.
To display all processes associated with the service, use:
sudo systemd-cgls --unit my.service
The available systemd-cgls options may differ between systemd versions. Check the supported syntax locally:
systemd-cgls --help
If a process is in the
Dstate,SIGKILLdoes not guarantee immediate termination. The process can exit only after it returns from the uninterruptible kernel wait. In this case, investigate stalled I/O, unavailable storage, a network file system, or a driver problem. A forced reboot should be the last resort after assessing the risk of data corruption.
Step 4. Stop the service, from the least disruptive method to the most forceful
Retry a normal stop
First, retry the normal stop operation while monitoring the journal:
sudo systemctl stop my.service
If the command waits indefinitely in an interactive session, open a second session and continue the diagnosis there. Do not run multiple parallel stop and restart commands. They add jobs to the queue but do not resolve the underlying cause of the hang.
Send SIGTERM to all service processes
If the processes do not exit normally, send them a termination signal through systemd:
sudo systemctl kill --kill-whom=all --signal=SIGTERM my.service
Then check the state again:
sudo systemctl status my.service --no-pager -l
sudo systemctl show my.service -p ActiveState -p SubState -p MainPID -p ControlPID
Force termination
If the process does not respond to SIGTERM, the data has been saved, or an abrupt shutdown is acceptable, send SIGKILL to all processes in the unit:
sudo systemctl kill --kill-whom=all --signal=SIGKILL my.service
Check whether the processes have disappeared:
sudo systemd-cgls --unit my.service
sudo systemctl status my.service --no-pager -l
If the PID remains and is in the D state, sending more signals will not resolve the problem. Inspect the kernel messages:
sudo journalctl -k -b --no-pager -n 200
Pay particular attention to messages about block device errors, I/O timeouts, hung tasks, NFS, FUSE, iSCSI, and file-system failures. The appropriate fix depends on the source of the wait: restoring the storage system, bringing the network resource back online, unmounting the problematic file system, or rebooting the host in a controlled manner.
Step 5. Return the unit to an operational state
After the stuck processes have exited, check the final state:
sudo systemctl is-active my.service
sudo systemctl is-failed my.service
sudo systemctl status my.service --no-pager -l
If the service has entered the failed state, clear the recorded failure state:
sudo systemctl reset-failed my.service
After resolving the underlying cause, start the service:
sudo systemctl start my.service
Verify the result:
sudo systemctl is-active my.service
sudo systemctl status my.service --no-pager -l
sudo journalctl -u my.service -b --no-pager -n 100
The expected verifiable result is that systemctl is-active prints active and the journal does not show a new cycle of a stuck stop operation. For a one-shot service, inactive may be the normal final state, depending on Type= and RemainAfterExit=.
Step 6. Fix the unit file to prevent the problem from recurring
Display the complete effective unit file, including override fragments:
sudo systemctl cat my.service
Do not edit the unit file under /usr/lib/systemd/system or /lib/systemd/system directly. A package upgrade may overwrite it. Create a drop-in instead:
sudo systemctl edit my.service
Example of a bounded stop configuration:
[Service]
TimeoutStopSec=30s
KillMode=control-group
SendSIGKILL=yes
TimeoutStopSec=30s is an example, not a universal value. A database, message queue, or application that performs lengthy state persistence may need more time. The value should exceed the normal graceful-shutdown duration measured from logs and metrics.
KillMode=control-group instructs systemd to terminate processes in the service control group rather than only the main process. This usually prevents a child process from remaining alive after its parent exits. Before changing this setting, confirm that the service does not intentionally start processes that must survive when the unit stops.
SendSIGKILL=yes allows systemd to apply final forced termination after the relevant timeout expires. Do not use SendSIGKILL=no without a clear operational reason, because an unresponsive process may leave the unit stuck while stopping.
After saving the override, verify the unit-file syntax:
sudo systemd-analyze verify my.service
Then reload the manager configuration:
sudo systemctl daemon-reload
Confirm that the expected settings are effective:
sudo systemctl show my.service \
-p TimeoutStopUSec \
-p KillMode \
-p SendSIGKILL
Checking ExecStop
If ControlPID was nonzero while the unit was stuck, the likely cause is an ExecStop= command. Retrieve its effective value:
sudo systemctl show my.service -p ExecStop
Review the stop script against the following criteria:
- it does not wait for interactive input;
- network requests and calls to external APIs have their own timeouts;
- any loop that waits for a PID has a time limit;
- the PID file is checked for freshness, and a PID is not used without verifying the corresponding process;
- a stop failure returns a nonzero exit code instead of being hidden by an infinite retry loop;
- the script does not start a background process and exit before the service has actually stopped.
Do not add ExecStop=/bin/kill -9 ... as the first solution. Systemd can already send signals to unit processes and track their cgroup. The ExecStop= command should perform application-specific graceful shutdown, while forced termination should be left to systemd’s timeout mechanism and kill policy.
Final checklist
- Check
ActiveState,SubState,MainPID, andControlPID. - Review the service journal for the current boot.
- Determine the state of the stuck process with
ps. - Inspect all processes in the service cgroup.
- Send
SIGTERMfirst, then useSIGKILLonly when the risk is acceptable. - If the process is in the
Dstate, diagnose I/O and inspect kernel messages. - After the processes exit, run
reset-failedand start the service. - Configure a justified
TimeoutStopSecvalue and verifyKillMode. - Validate the unit with
systemd-analyze verifyand confirm the effective settings withsystemctl show.
Sources
The following are official systemd project pages. To match the installed version precisely, also use the local man systemctl, man systemd.service, and man systemd.kill commands. The current contents of the online pages cannot be verified in this environment, so version-specific differences should be checked against the local package documentation.