Systemd兼容SysV init.d脚本:启动正常但停止失效求助
Hey there! Let's figure out why your stop command isn't doing what it's supposed to. Looking at the snippet you shared, the issue is pretty straightforward—your stop case only logs a failure message, but doesn't actually include any logic to terminate your service's process. Let's fix that step by step.
The Core Problem
Right now, when you run service test stop, your script just prints "Stop!" but doesn't send any signals to the running test process or clean up associated files (like PID files). Systemd or the init system can't guess how to stop your service—you have to tell it explicitly.
Fixing the Stop Logic
Here's how to update your script with proper stop functionality, using standard LSB tools that play nice with Systemd:
First, make sure you're using start-stop-daemon (it's part of the lsb-base package you already depend on) to safely manage your process. This tool handles PID files, signal retries, and process cleanup reliably.
Updated Script Snippet
#!/bin/sh # ### BEGIN INIT INFO # Provides: test # Required-Start: $remote_fs $syslog # Required-Stop: $remote_fs $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Test. # Description: Test. # ### END INIT INFO # Define LSB log_* functions. . /lib/lsb/init-functions # Path to your service executable SERVICE_EXEC="/path/to/your/test/service" # PID file location (most services write this automatically, or you can set it) PID_FILE="/var/run/test.pid" case "$1" in start) log_daemon_msg "Starting test service" "test" # Start the service in background, create PID file start-stop-daemon --start --background --make-pidfile --pidfile $PID_FILE --exec $SERVICE_EXEC log_end_msg $? ;; stop) log_daemon_msg "Stopping test service" "test" # Check if PID file exists first if [ -f $PID_FILE ]; then # Send TERM signal (graceful shutdown), wait 30s, then send KILL if needed start-stop-daemon --stop --pidfile $PID_FILE --retry TERM/30/KILL/5 # Clean up the PID file after process stops rm -f $PID_FILE log_end_msg $? else log_warning_msg "Test service isn't running (no PID file found)" log_end_msg 1 fi ;; status) # Optional: Add status check logic status_of_proc -p $PID_FILE $SERVICE_EXEC "test" && exit 0 || exit $? ;; restart|force-reload) $0 stop sleep 1 $0 start ;; *) echo "Usage: $0 {start|stop|status|restart|force-reload}" exit 2 ;; esac
Key Changes Explained
- Added variables for your service executable and PID file to keep the script clean.
- In the
stopcase:- Checks if the PID file exists to avoid errors when the service isn't running.
- Uses
start-stop-daemonto send aTERMsignal first (for graceful shutdown), waits 30 seconds, and sends aKILLsignal if the process won't exit. - Cleans up the PID file once the process is stopped.
- Added optional
statusandrestartcases for better service management.
Bonus: Consider a Systemd Unit File (Better Compatibility)
Since you're targeting Systemd, writing a native .service file is often simpler and more reliable than a traditional init script. Here's an example:
[Unit] Description=Test Service After=remote-fs.target syslog.target [Service] ExecStart=/path/to/your/test/service PIDFile=/var/run/test.pid Restart=on-failure # Optional: Auto-restart if service crashes [Install] WantedBy=multi-user.target
To use this:
- Save it as
/etc/systemd/system/test.service - Run
sudo systemctl daemon-reloadto load the new unit - Enable it on boot with
sudo systemctl enable test - Start/stop it with
sudo systemctl start testorsudo systemctl stop test
Systemd handles all the stop logic automatically here, so you don't have to write any process termination code yourself.
Final Checks
- Make sure your script has execute permissions:
sudo chmod +x /etc/init.d/test - If you stick with the init script, update the
SERVICE_EXECandPID_FILEpaths to match your actual service.
内容的提问来源于stack exchange,提问作者Crankycyclops

