SABnzbd : Une interface web pour gérer les newsgroups

From Deimos.fr / Bloc Notes Informatique
Jump to: navigation, search
Sabnzbd

Software version 0.6.15+
Operating System Debian 6/7
Website Sabnzbd Website
Last Update 19/06/2013
Others

1 Introduction

Vous n'avez peut être pas envie d'avoir un soft lourd qui tourne sur votre machine pour faire des newsgroups. C'est alors qu'un pote me parle de SABnzbd. Après avoir regardé un peu comment ça fonctionne, il s'avère effectivement que c'est particulièrement redoutable.
J'ai donc décidé de faire une petite documentation pour la mise en place sur une Debian Squeeze.

2 Installation

Voici le minimum à installer pour Debian 6 :

Command aptitude
aptitude install python-cheetah python-pyopenssl python-yenc

Pour Debian 7 :

Command aptitude
aptitude install python-cheetah python-openssl python-yenc

Puis nous allons installer SABnzbd :

Command
cd /var/www
wget "http://downloads.sourceforge.net/project/sabnzbdplus/sabnzbdplus/sabnzbd-0.6.15/SABnzbd-0.6.15-src.tar.gz?r=http%3A%2F%2Fsabnzbd.org%2Fdownload%2F&ts=1332934860&use_mirror=freefr" -o sab.tgz
tar -xzf sab.tgz
mv SABnzbd-0.6.15 sabnzbd
cd sabnzbd

3 Configuration

3.1 Apache

Vous n'avez peut être pas envie de devoir taper un autre port pour accéder à l'interface web. Le but donc est de le mettre derrière Apache qui fera lui même la redirection. Il va déjà falloir activer le module proxy d'apache :


Command aptitude
aptitude install apache2 apache2-utils apache2.2-common libapache2-mod-proxy-html

Then activate modules :

Command a2enmod
a2enmod proxy_connect
a2enmod proxy_http
a2enmod proxy_html

And restart Apache.

Et voici la configuration à appliquer et adapter à vos besoins :

Configuration File /etc/apache2/sites-enabled/000-default
[...]
<Location /sabnzbd>
order deny,allow
deny from all
allow from all
ProxyPass http://localhost:8080/sabnzbd
ProxyPassReverse http://localhost:8080/sabnzbd
</Location>

4 Lancement

Pour lancer le seveur :

Command python
python ./SABnzbd.py -d

Connectez vous ensuite sur http://localhost/SABnzbd (ou http://localhost:8080/SABnzbd si vous n'avez pas mis de conf apache) et configurez comme le vous voulez.

5 Scripts de post-traitement

Il est possible que vous souhaitiez qu'une action se fasse automatiquement après chaque téléchargement. Dans mon cas, je souhaites que les fichiers présents ne restent pas plus de 15 jours. J'ai donc un script qui me fait le nettoyage que j'ai placé en crontab :

Command /etc/scripts/delete_old_files.sh
#!/bin/sh
folder="/mnt/sabnzbd/downloads"
max_day=15
 
for user in `ls $folder/` ; do
    cd $folder
    find . -mtime +$max_day ! -name '.' ! -exec rm -f {} \;
    find . -type d ! -name '.' ! -name '..' -exec rmdir {} \;
done

Le soucis c'est qu'il me dégage des fichiers qui ont été créer il y a plus de 15 jours mais que j'ai téléchargé il y a moins de 15 jours.
Exemple : je télécharge une ISO Ubuntu qui date d'il y a 5 mois. Elle figure dans un fichier compressé (zip par exemple) que je télécharge, Sabnzbd s'occupe de le décompresser, mais le fichier au final date d'il y a 5 mois et non de la date de décompression. Il faut donc une solution pour modifier la date du fichier à aujourd'hui. Créons par exemple un dossier de scripts :

Command mkdir
mkdir -p /etc/scripts/sabnzbd

Puis nous allons mettre un script de post traitement :

Configuration File /etc/scripts/sabnzbd/postscript.sh
#!/bin/sh
tmp_renamed_folder=`echo "$1" | perl -pe 's/\ |-/_/g'`
renamed_folder=`echo "$tmp_renamed_folder" | perl -pe 's/_+/_/g'`
mv "$1" $renamed_folder 2>/dev/null
find $renamed_folder -exec touch {} \;
exit 0

Ce script renomme les dossiers contenant un - ou des espaces par des _. Et il concatène les multiples _ par un seul. Ensuite il change la date des fichiers et dossier. Pourquoi faire ça alors que des options de renommage sont disponibles directement dans SABnzbd ? Tout simplement parce que ces opérations se font lors de l'import d'un nzb et non lors d'un renommage. Mais vu que ça pose des problèmes pour la commande find, j'ai choisis de faire du renommage.

Mettez les bons droits :

Command chmod
chmod 755 /etc/scripts/sabnzbd/postscript.sh

Pour savoir comment ça fonctionne, je vous invite à lire ce lien[1]

Ensuite, configurez comme ceci Sabnzbd (depuis l'interface web) pour qu'il connaisse le lieu de vos scripts et qu'il les utilise automatiquement :

  1. Configuration -> Répertoires -> Dossier des scripts de post-traitement -> /etc/scripts/sabnzbd
  2. Configuration -> Catégories -> Par Défaut -> Script -> postscript.sh

Et voilà :-). Vos téléchargements seront post processés et auront la date et l'heure de fin de téléchargement des fichiers :-)

6 Améliorer les performances

6.1 Sabnzbd

Par défaut, le téléchargement et le yencode se passe sur disque. Il est possible de tout faire en RAM. Évidement c'est consommateur de RAM, mais la différence de vitesse est phénoménale ! C'est à dire que vous doublerez au moins les performances ! Personnellement j'ai quadruplé les vitesses de download :-). Voici comment j'ai procédé, allez dans l'interface graphique puis :
Configuration -> Générale -> Réglages -> Limite d'article en cache -> 250M

6.2 Système

Au niveau du système, activez le noatime sur vos partitions[2].

7 Outils tiers

7.1 Firefox

Je vous recommande nzbdStatus pour Firefox et SABMobile pour iPhone ou pour Android.

7.2 sabnzbd_api.py

J'ai écris un script en python permettant de jouer avec l'API que délivre Sabnzbd. Je l'ai créer dans l'idée qu'il soit facile de rajouter une fonctionnalité via l'API. Ce script permet :

  • De voir les éléments que fournit l'API XML
  • De supprimer un certain nombre d'éléments dans l'historique

Voici le script. Editez le début du script et insérez l'URL, ainsi que la clé API  :

Configuration File sabnzbd_api.py
#!/usr/bin/env python
# Made by Deimos <[email protected]>
# Under GPL2 licence
 
# Set Sabnzbd URL
sabnzbd_url = 'http://127.0.0.1:8080/sabnzbd'
# Set Sabnzbd API
sabnzbd_api = '2d872eb6257123a9579da906b487e1de'
 
#############################################################
 
# Load modules
import argparse
from urllib2 import Request, urlopen, URLError
from lxml import etree
import sys
 
def Debug(debug_text):
    """Debug function"""
    if debug_mode == True:
        print debug_text
 
def args():
    """Command line parameters"""
    # Define globla vars
    global sabnzbd_url, sabnzbd_api, debug_mode, mode, keep_history
 
    # Main informations
    parser = argparse.ArgumentParser(description="Sabnzbd API usage in python")
    subparsers = parser.add_subparsers(title='Available sub-commands', help='Choose a subcommand (-h for help)', description='Set a valid subcommand', dest="subcmd_name")
    # Default args
    parser.add_argument('-u', '--url', action='store', dest='url', type=str, default=sabnzbd_url, help='Set Sabnzbd URL (default : %(default)s)')
    parser.add_argument('-a', '--api', action='store', dest='api', type=str, default=sabnzbd_api, help='Set Sabnzbd API key')
    parser.add_argument('-v', '--version', action='version', version='v0.1 Licence GPLv2', help='Version 0.1')
    parser.add_argument('-d', '--debug', action='store_true', default=False, help='Debug mode')
    # Show XML API
    parser_xa = subparsers.add_parser('xa', help='Show XML Elements from API')
    # Delete history
    parser_dh = subparsers.add_parser('dh', help='Delete old history')
    parser_dh.add_argument('-k', '--keep', action='store', dest='num', type=int, default=150, help='Number of items to keep in history (default : %(default)s)')
 
    result = parser.parse_args()
 
    # Set debug to True if requested by command line
    if (result.debug == True):
        debug_mode=True
    else:
        debug_mode=False
    # Send debug informations
    Debug('Command line : ' + str(sys.argv))
    Debug('Command line vars : ' + str(parser.parse_args()))
 
    # Check defaults options
    if result.url != sabnzbd_url:
        sabnzbd_url = result.url
    elif result.api != sabnzbd_api:
        sabnzbd_api = result.api
 
    # Managing options
    mode=result.subcmd_name
    if (mode == 'dh'):
        keep_history=result.num
 
def GetSabUrl(sabnzbd_url, sabnzbd_api):
    """Concat Sabnzbd URL
    Check that the connection to URL is correct and TCP is OK"""
    # Concat
    sab_url = sabnzbd_url + '/api?mode=history&output=xml&apikey=' + sabnzbd_api
    Debug('Concatened Sabnzbd URL : ' + str(sab_url))
 
    # Connectivity test
    request = Request(sab_url)
    try:
        response = urlopen(request)
    except URLError, e:
        if hasattr(e, 'reason'):
            print 'Can\'t connect to server : ' + str(e.reason)
            sys.exit(1)
        elif hasattr(e, 'code'):
            print 'The server couldn\'t fulfill the request.' + str(e.code)
            sys.exit(1)
    else:
        Debug('Sabnzbd TCP connection OK')
    return sab_url
 
def GetXmlHistory(sab_url):
    """Get XML nzo_id entries"""
    xml_history =  []
    # Parse XML from given url
    xml_content = etree.parse(sab_url)
    # Select only the wished tag and push it in xml_history list
    for node in xml_content.xpath("///*"):
        if (node.tag == 'nzo_id'):
            # Reencode value to avoid errors
            tag_value = unicode(node.text).encode('utf8')
            #Debug(node.tag + ' : ' + tag_value)
            xml_history.append(tag_value)
    Debug('XML history has ' + str(len(xml_history)) + ' entries')
 
    # If there were no entry in the list, check if the API failed
    if len(xml_history) == 0:
        Debug('Checking why there is no datas')
        xml_content = etree.parse(sab_url)
        for node in xml_content.xpath("//*"):
            if (node.tag == 'error'):
                print 'Can\'t connect to server : ' + unicode(node.text).encode('utf8')
                sys.exit(1)
 
    return xml_history
 
def DeleteHistory(xml_history,keep_history):
    """Delete old history"""
    # Create a new list contaning elements to remove
    elements2delete = []
    element_number=1
    for element in xml_history:
        if element_number > keep_history:
            elements2delete.append(element)
        element_number += 1
    queue_elements2remove=','.join(elements2delete)
    Debug('Elements to delete (' + str(len(xml_history)) + ' - ' + str(keep_history)  + ' = ' + str(len(elements2delete))  + ')')
 
    # Concat URL with elements to remove and then remove
    sab_url_remove = sabnzbd_url + '/api?mode=history&name=delete&value=' + queue_elements2remove + '&apikey=' + sabnzbd_api
    urlopen(sab_url_remove)
 
def ShowXMLElements(sab_url):
    """Show XML code from URL"""
    xml_content = etree.parse(sab_url)
    for node in xml_content.xpath("//*"):
        print node.tag + ' : ' + unicode(node.text).encode('utf8')
 
def main():
    """Main function that launch all of them"""
    # Set args and get debug mode
    args()
    # Get Sabnzbd URL and check connectivity
    sab_url = GetSabUrl(sabnzbd_url, sabnzbd_api)
    # Delete old history
    if mode == 'dh':
        xml_history = GetXmlHistory(sab_url)
        DeleteHistory(xml_history,keep_history)
    elif mode == 'xa':
        ShowXMLElements(sab_url)
 
if __name__ == "__main__":
    main()

Pour la partie utilisation, elle se découpe en 2 :

  • Les commandes principales
  • Les sous commandes (fonctions demandées)

Voici comment l'utiliser :

Command sabnzbd_api.py
> sabnzbd_api.py -h
usage: sabnzbd_api.py [-h] [-u URL] [-a API] [-v] [-d] {xa,dh} ...
 
Sabnzbd API usage in python
 
optional arguments:
  -h, --help         show this help message and exit
  -u URL, --url URL  Set Sabnzbd URL (default : http://127.0.0.1:8080/sabnzbd)
  -a API, --api API  Set Sabnzbd API key
  -v, --version      Version 0.1
  -d, --debug        Debug mode
 
Available sub-commands:
  Set a valid subcommand
 
  {xa,dh}            Choose a subcommand (-h for help)
    xa               Show XML Elements from API
    dh               Delete old history

Pour utiliser la sous commande dh qui permet de supprimer l'historique :

Command sabnzbd_api.py
> sabnzbd_api.py dh -h
usage: sabnzbd_api.py dh [-h] [-k NUM]
 
optional arguments:
  -h, --help          show this help message and exit
  -k NUM, --keep NUM  Number of items to keep in history (default : 150)

Ici, si je supprime -h, il supprimera l'historique de queue suppérieur à 150 entrées.

8 References

  1. ^ http://wiki.sabnzbd.org/user-scripts
  2. ^ Optimisation des filesystems extX et du RAID sous Linux#noatime