Page 1 of 1

Properly shutting down sabnzbd

Posted: December 17th, 2012, 4:16 pm
by revelation60
I am the package maintainer of sabnzbd for Arch Linux and I want to write a decent systemd service file. The problem is however in closing sabnzbd. The only supported way seems to be through use of the web interface. This is very inconvenient, since this requires storing the API key and some other details in systemd environment files.

This is the current service file:

Code: Select all

[Unit]
Description=SABnzbd binary newsreader
After=network.target

[Service]
EnvironmentFile=/etc/conf.d/sabnzbd_systemd
ExecStart=/bin/sh -c "python2 ${SABNZBD_DIR}/SABnzbd.py ${SABNZBD_ARGS} --pid /run/sabnzbd"
ExecStop=/usr/bin/curl -f "${SABNZBD_PROTOCOL}://${SABNZBD_USPW}${SABNZBD_IP}:${SABNZBD_PORT}/sabnzbd/api?mode=shutdown&apikey=${SABNZBD_KEY}"
Type=forking
PIDFile=/run/sabnzbd/sabnzbd-8080.pid
User=sabnzbd
Group=sabnzbd

[Install]
WantedBy=multi-user.target
However, the thing with the PID is not working out properly (among others, with restarts). So in order to clean up the file I want to have a simpler configuration file, like:

Code: Select all

[Unit]
Description=SABnzbd binary newsreader
After=network.target

[Service]
Type=simple
ExecStart=/bin/sh -c "python2 /opt/sabnzbd/SABnzbd.py"
User=sabnzbd
Group=sabnzbd

[Install]
WantedBy=multi-user.target
This file is currently missing an ExecStop, since there seems to be no easy/safe way to stop sabnzbd. So my question is the following:

Is there a supported way, other than the web interface, to safely stop sabnzbd?

Re: Properly shutting down sabnzbd

Posted: December 17th, 2012, 4:24 pm
by sander
Did you check /etc/init.d/sabnzbdplus from the PPA for Ubuntu?

A snippet:

Code: Select all

stop_sab() {
        load_settings || exit 0
        if is_running; then
                TMPFILE="$(mktemp --tmpdir sabnzbdplus.XXXXXXXXXX)"
                [ $? -eq 0 ] || exit 1
                trap '[ -f "$TMPFILE" ] && rm -f "$TMPFILE"' EXIT
                echo "$PID" > "$TMPFILE"
                log_daemon_msg "Stopping $DESC"
                start-stop-daemon --stop --user ${USER%:*} --pidfile "$TMPFILE" --retry 30
                check_retval
        else
                log_success_msg "$DESC: not running"
        fi
        [ -f $PIDFILE ] && rm -f $PIDFILE
}
HTH

Re: Properly shutting down sabnzbd

Posted: December 17th, 2012, 4:33 pm
by revelation60
Well, this just checks the PID and kills the process. But is this safe? And what's also somewhat inconvenient is that the sabnzbd PID filename has the port included. This requires the user to change the port in an environment file.

Re: Properly shutting down sabnzbd

Posted: December 17th, 2012, 4:46 pm
by sander
Well, it works, so apparently it is safe.

If you want to use API anyway, maybe this helps: if you can stop the process, I guess you can read the sabnzbd.ini SABnzbd is using. So you can then read the API key, and use that ...

Re: Properly shutting down sabnzbd

Posted: December 17th, 2012, 5:04 pm
by revelation60
Killing the process always works to shut it down, but that doesn't mean it's safe. For example, I don't know for sure if the downloads in the queue are properly paused or if files are guaranteed not to get corrupted. Parsing the file could work, although it's not a very clean way of doing this.

Re: Properly shutting down sabnzbd

Posted: December 17th, 2012, 5:11 pm
by sander
Well, I checked, and a "kill <SAB-pid>" seems to get beautifully caught by SAB, as it prints to stdout:

Code: Select all

2012-12-17 23:09:47,799::WARNING::[__init__:169] Signal 15 caught, saving and exiting...
2012-12-17 23:09:47,800::INFO::[nzbqueue:211] Saving queue
2012-12-17 23:09:47,800::INFO::[__init__:897] Saving data for queue9.sab in /home/sander/.sabnzbd/admin/queue9.sab
2012-12-17 23:09:47,801::INFO::[__init__:897] Saving data for totals9.sab in /home/sander/.sabnzbd/admin/totals9.sab
2012-12-17 23:09:47,801::INFO::[__init__:897] Saving data for rss_data.sab in /home/sander/.sabnzbd/admin/rss_data.sab
2012-12-17 23:09:47,803::INFO::[__init__:897] Saving data for bookmarks.sab in /home/sander/.sabnzbd/admin/bookmarks.sab
2012-12-17 23:09:47,804::INFO::[__init__:897] Saving data for watched_data.sab in /home/sander/.sabnzbd/admin/watched_data.sab
2012-12-17 23:09:47,804::INFO::[postproc:84] Saving postproc queue
2012-12-17 23:09:47,805::INFO::[__init__:897] Saving data for postproc1.sab in /home/sander/.sabnzbd/admin/postproc1.sab
sander@R540:~/SABnzbd-0.7.7$ 
So ... that makes it safe.

Re: Properly shutting down sabnzbd

Posted: December 17th, 2012, 5:24 pm
by jcfp
You cannot really guarantee a clean shutdown, in the sense that (afaik) external utils (par2/unrar/postproc scripts) aren't killed by sab if you tell the program to shut down while those just happen to be running. Killing the process directly isn't a problem though: sab responds to signal 15 (and most other signals, for that matter) with a regular program shutdown, no different or less clean from using web request/api, ^C, or the shutdown button in the web interface.

That just leaves the selection of the proper process. As you're no doubt aware, the pid changes after a restart from the web interface. The name of the pid file unfortunately includes the port number, which is indeed inconvenient for init scripts because it requires prior knowledge of the user's configuration to known the name of the pid file. Similar knowledge is required for using the api to do the shutdown. So I ended up with searching for the pid using pgrep. If/when the full name of the pidfile can be enforced through startup options, I would probably switch to that. I think this has been requested but I don't remember the outcome of the discussion.

Re: Properly shutting down sabnzbd

Posted: November 21st, 2023, 12:46 pm
by rubruz1
i'm sure this has been already sorted by many, but just as this is the first google result, this is how I do it

Code: Select all

npm install sabnzbd
Run with node the following JS

Code: Select all

const SABnzbd = require('sabnzbd');
const sabnzbd = new SABnzbd('http://sab_host_IP:8080/', 'YOUR_API_KEY');

sabnzbd.cmd('shutdown');
the sabnzb npm package has plenty of objects, so you can add logic such as checking the queue status, etc..