Skip to content

Installer Matomo sur Debian 9

Imaginons qu’Airgan, une plateforme communautaire payante de location et de réservation d’organes, veuille améliorer le suivi des visites sur son site web. Matomo est une réponse possible à ce besoin.

Matomo, anciennement Piwik, est un service web pour collecter des statistiques de visites. L’entreprise propose une version libre, auto-hébergeable et une version hébergée uniquement par Matomo qui inclut des fonctions non disponibles dans la version libre.

Matomo fournit un fichier .deb, permettant d’installer le service facilement sur une machine Debian. Cet article présente quelques éléments à prendre en compte.

Le changement de nom de Piwik à Matomo date de Janvier 2018. Tout n’a pas été transféré et la documentation ou les variables laissent parfois encore apparaître l’ancien nom.

Installation du paquet piwik

Le paquet n’est pas inclus dans la distribution mais est fourni dans un dépôt tiers géré par Matomo.
La documentation pour installer le paquet fourni par Matomo est disponible à http://debian.piwik.org/. Il suffit de la suivre.

Installation du paquet php-mbstring

Le fonctionnement du service nécessite que le paquet php-mbstring soit installé. Si ce n’est pas le cas, une erreur lors de la configuration de Matomo (dans quelques étapes, patientez !) sera affichée :

Capture d'écran de l'erreur

Une pull-request sur Github a été faite pour ajouter php-mbstring aux dépendances. Cette étape ne sera peut-être plus nécessaire dans la prochaine version ?

Configuration du service web

Le paquet ne dépend pas d’un serveur web en particulier. Le code d’example suivant suppose que c’est Apache2 qui est installé. N’importe quel autre serveur web fonctionnerait aussi.

<VirtualHost 19.84.19.84:80>
    ServerName matomo.airgan.tld

    # ce sera bien pratique quand on aura des problèmes
    ErrorLog /srv/airgan/logs/matomo-http-error.log
    CustomLog /srv/airgan/logs/matomo-http-access.log combined
    LogLevel info

    # les deux lignes importantes
    DocumentRoot /usr/share/piwik
    DirectoryIndex index.php
</VirtualHost>

Ensuite, il faut activer le virtualhost :
sudo a2ensite matomo.conf
sudo systemctl reload apache2

Ajouter un utilisateur pour la base de données

Un serveur de base de données MySQL ou MariaDB doit être installé. Ensuite, il faut se connecter sur ce serveur pour créer un utilisateur qui pourra créer la base de données et les tables nécessaires lors de la configuration de Matomo (c’est juste après cette étape, vous avez bien fait de patienter !).

#Créer un utilisateur nommé matomo :
CREATE USER matomo@'localhost';
SET PASSWORD FOR matomo@'localhost' = PASSWORD('secret');
#Lui donner les droits pour créer la base de données nécessaire au service :
GRANT CREATE, ALTER, SELECT, INSERT, UPDATE, DELETE, DROP, CREATE TEMPORARY TABLES on *.* to matomo@'localhost';

Configurer le service Matomo

Avec un navigateur web, allez sur le domaine paramétré dans la configuration du serveur web (matomo.airgan.tld dans notre exemple). Il suffit de suivre les étapes de l’interface pour finir l’installation. Elle correspond à l’étape « The 5-minute Matomo Installation » sur https://matomo.org/docs/installation/.

Une fois cette étape terminée, l’installtion est terminée et aller sur le domaine permet de voir l’interface de connexion pour accéder aux statistiques de visite.

Versions utilisées

L’installation ayant servie à écrire l’article a été faite sur
Debian GNU/Linux 9.3 (stretch) avec les versions suivantes des paquets :

apache2
2.4.25-3+deb9u4
mariadb-server
10.1.26-0+deb9u1
piwik
3.2.1-1

Dans le futur, il est possible que la livraison des organes se fasse à vélo. À étudier dans un prochain business plan.

Publicités

Modèles féminins en informatique

Les informaticiens célèbres sont principalement des hommes, qu’ils soient théoriciens, créateurs de langage ou de logiciels. À l’origine de l’informatique, beaucoup de femmes étaient présentes mais en tant que petites mains plutôt que conceptrices. Voici quelques femmes qui pourraient servir de modèles :

Ada Lovelace

Difficile de ne pas citer Ada Lovelace car elle est considérée comme la première personne à avoir écrit un programme, et cela, bien avant qu’un ordinateur existe. Avec l’importance grandissante de l’informatique, son influence a été reconnue et un langage créé dans les années 80 porte son prénom. Un prix décerné par l’AWC, une association de femmes dans l’informatique, porte aussi son nom.

Margaret Hamilton

Peu de personnes ont écrit avec leur équipe un code source qui, une fois, imprimé est aussi haut qu’eux. Margaret Hamilton, elle peut. Surtout que ce code, probablement écrit en assembleur, est parti dans l’espace…

Suite à son expérience des développements logiciels sur le programme Apollo, Margaret Hamilton a aussi publié des articles importants sur l’ingéniérie logicielle et conçu le langage 001AXIS Universal Systems Language.

Lorinda Cherry

Lorinda Cherry a été embauchée par les Bell Labs pour programmer en assembleur (un classique dans les années 70) et a alors participé au développement d’outils sur l’Unix originel. Elle a conçu à cette période un langage pour afficher des équations (eqn) avec Brian Kernighan. Elle a aussi contribué à Plan 9.

Lorinda Cherry fait une rapide intervention sur une vidéo de 1982 qui présente Unix AT&T. Son intervention commence à 15 minutes 39.

Elles ont raté le podium : Grace Hopper, Jean Bartik, Betty Holberton ou Mary Lee Woods.

Avec with : plus d’indentations, moins d’instructions

En python, le mot-clef with permet d’ouvrir un bloc dans lequel un contexte spécifique est actif.

L’exemple de « context manager » le plus courant est celui d’une ouverture de fichier qui se ferme automagiquement :

with open('sortie.txt', 'w') as f:
    f.write('Coucou')
f.closed # vaut True

On retrouve cette possibilité dans de nombreux cas comme l’ouverture d’un serveur SMTP :

from smtplib import SMTP
with SMTP("domain.org") as smtp:
    # faire des trucs
#la connection smtp est fermée

L’utilisation d’un « context manager » est adapté à chaque fois qu’il est nécessaire de réaliser des tâches à l’ouverture ou la fermeture (libérer un verrou, fermer une connection, supprimer un fichier, changer une variable globale, etc.). Cela permet de se concentrer ce qu’on veut vraiment faire dans le contexte du with. Les tâches d’ouverture et fermetures sont respectivement déplacées dans les méthodes magiques __enter__() et __exit__(). Si l’on prend en compte l’ensemble du code source, il n’y a donc pas moins d’instructions. Et le titre de l’article peut être considérée comme de la publicité mensongère.

class Pipeau:

    def __enter__(self):
        print("<bonimenteur>")

    def __exit__(self, type, value, traceback):
        print("</bonimenteur>")

with Pipeau():
    print("Prochain article de blog à -50 % !")

# affiche :
# <bonimenteur>
# Prochain article de blog à -50 % !
# </bonimenteur>

Pour plus de détails sur l’utilisation de with, consultez la documentation Python et l’article de sametmax.

Ignorer des fichiers, de ack à ag

Ag (the silver searcher), comme ack permettent de chercher des motifs de texte dans du code source. Une sorte de grep spécialisé pour du code source.

Les deux outils sont très probablement disponibles dans votre distribution préférée.
Sous Debian et dérivées :

apt install ack-grep # pour ack
apt install silversearcher-ag # pour ag

ag est plus rapide qu’ack pour trouver des motifs. Un comparatif de performance écrit par le développeur d’ag, qui est donc juge et partie, le montre. Quelques tests rapides m’ont aussi montré un gain de temps.

ack utilise un fichier .ackrc pour ignorer des chemins ou fichiers. ag aussi, mais le format est un peu différent (équivalent à .hgignore et .gitignore qu’il utilise aussi) car il ne fait que de l’exclusion. La modification est triviale pour un castor junior :

$ cat .ackrc
--ignore-dir=riri
--ignore-dir=fifi/
--ignore-dir=loulou

devient
$ cat .ignore
riri
fifi/
loulou

À partir de la version 0.33.0, ag utilise le fichier .ignore et .agignore devient déprécié. Dans la dernière version testée, le fichier .agignore est toujours lu s’il est la racine de ${HOME}, mais non pris en compte s’il est dans le répertoire dans lequel la recherche est faite.

Testé avec les versions suivantes :

ack version 2.12 et 2.18
ag version 0.19.2 et 2.1.0

Coder une variante de FizzBuzz basée sur le jeu 6 qui prend

FizzBuzz est un jeu où l’on compte : lorsqu’un entier est un multiple de 3, on dit « Fizz », multiple de 5 « Buzz », multiple de 3 et 5 « FizzBuzz », dans les autres cas, on dit simplement l’entier. Il est aussi utilisé comme test pour évaluer si quelqu’un maîtrise les bases de la programmation. Une variante, un peu plus compliquée, mais du même type pourrait être réalisée avec le jeu 6 qui prend.

C’est un jeu de cartes dont le but est d’avoir le moins de têtes de bœufs. Les cartes sont numérotées de 1 à 104 (inclus).

Les règles d’estimation de la valeur (en tête de bœufs) des cartes sont relativement similaires aux règles du FizzBuzz :

  • si le nombre est un multiple de 5, la carte vaut 2 têtes de bœufs
  • si le nombre est un multiple de 10, la carte vaut 3 têtes de bœufs
  • si le chiffre des dizaines et des unités sont identiques, la carte vaut 5 têtes de bœufs
  • la carte 55 vaut 7 têtes de bœufs
  • les autres cartes valent 1 tête de bœufs chacune

TL; DR Si on a vraiment du temps à perdre, on finit avec un code de ce genre :

CARTES = 104

def tetes(numero):
    _score = 1
    for diviseur, points in ((10, 1), (5, 1), (11, 4)):
        if _est_multiple(numero, diviseur):
            _score += points
    if numero == 55:
        _score += 1
    return _score

def _est_multiple(numero, diviseur):
    return not numero % diviseur

if __name__ == "__main__": 
    for numero in range(1, CARTES + 1):
        print(numero, "★" * tetes(numero))

Le début de la sortie du terminal :

1 ★
2 ★
3 ★
4 ★
5 ★★
6 ★
7 ★
8 ★
9 ★
10 ★★★
11 ★★★★★
12 ★

Première version

Le code le plus rapide à écrire pour passer les tests devrait ressembler à :

def tetes(numero):
    if numero == 55:
        return 7
    if not numero % 10:
        return 3
    elif not numero % 5:
        return 2
    elif numero >= 10 and str(numero)[0] == str(numero)[1]:
        return 5
    else:
        return 1

if __name__ == "__main__": 
    for numero in range(1, 12):
        print(numero, "*" * tetes(numero))

Améliorations

La règle « le chiffre des dizaines et des unités sont identiques » est équivalent à être un multiple de 11 :

#if numero >= 10 and str(numero)[0] == str(numero)[1]:
if not numero % 11:

Autant factoriser le test de divisibilité :

def tetes(numero):
    _score = 1
    if _est_multiple(numero, 10):
        _score += 1
    if _est_multiple(numero, 5):
        _score += 1
    if _est_multiple(numero, 11):
        _score += 4
    if numero == 55:
        _score += 1
    return _score

def _est_multiple(numero, diviseur):
    return not numero % diviseur

On peut alors remplacer la succession de if par une boucle, et hop, on obtient un code final (qui est au début de l’article).

Tests

Pour valider le programme, quelques assertions de bon aloi sont à ajouter. Ces assertions auront été obtenues au fur et à mesure si on fait du TDD.

import sixquiprend

assert 1 == sixquiprend.tetes(1)
assert 1 == sixquiprend.tetes(2)
assert 2 == sixquiprend.tetes(5)
assert 3 == sixquiprend.tetes(10)
assert 5 == sixquiprend.tetes(11)
assert 5 == sixquiprend.tetes(22)
assert 7 == sixquiprend.tetes(55)