Blog ENI : Toute la veille numérique !
En raison d'une opération de maintenance, le site Editions ENI sera inaccessible le mardi 10 décembre, en début de journée. Nous vous invitons à anticiper vos achats. Nous nous excusons pour la gêne occasionnée
En raison d'une opération de maintenance, le site Editions ENI sera inaccessible le mardi 10 décembre, en début de journée. Nous vous invitons à anticiper vos achats. Nous nous excusons pour la gêne occasionnée
  1. Livres et vidéos
  2. Scripting Python sous Linux
  3. Exemples
Extrait - Scripting Python sous Linux Développez vos outils système (2e édition)
Extraits du livre
Scripting Python sous Linux Développez vos outils système (2e édition)
3 avis
Revenir à la page d'achat du livre

Exemples

Introduction

Ce chapitre, comme son titre le précise, est dédié aux exemples de scripts.

Le premier script, qui servira d’échauffement est un exemple de génération d’arborescence de fichiers dont le nom et le contenu sont aléatoires. Ainsi, plus besoin d’utiliser de vrais fichiers en exploitation, avec les risques que cela comporte, pour faire des tests.

Puis nous verrons un petit script ayant servi de nombreuses fois sur des systèmes pour analyser sur un mois l’utilisation d’un serveur.

Et pour des analyses plus poussées, pourquoi pas un instantané des processus en cours où l’essentiel des informations serait dans une base de données ?

Ensuite, pourquoi ne pas tester l’accès Internet, ce script utilisant la même base de données que la plupart des utilitaires de supervision.

Puis, l’étude d’un cas concret et complexe d’exécution de requête sur une base MySQL distante, utile pour bien comprendre l’intérêt d’investir dans un ETL.

Ce chapitre se clôture avec un exemple regroupant plusieurs modules dont WSGI, Bottle et Jinja, qui tente d’améliorer la présentation standard de la page d’index d’Apache.

Génération de fichiers et répertoires aléatoire

Très souvent, il serait judicieux d’avoir à disposition des répertoires et des fichiers en nombre suffisant pour effectuer des tests.

Bien entendu, il est possible de récupérer des sauvegardes, d’utiliser les fichiers des collègues, mais cela peut parfois être mal vu.

De plus, si vous avez une gestion stricte et obligatoire du RGPD, vous serez obligé de déclarer ce genre de traitement.

Aussi, voici un petit utilitaire pour générer de manière aléatoire une arborescence de répertoires avec des fichiers nommés aléatoirement et au contenu lui-même aléatoire.

Son utilisation est simple : d’abord, ajuster les paramètres dans le script, puis le lancer.

Voici la description des paramètres :

Paramètre

Défaut

Description

max_rep

5

Nombre maximum de répertoires de base générés aléatoirement

max_files

5

Nombre maximum de fichiers générés aléatoirement par répertoire

MAX_NIVEAU

3

Niveau maximum d’arborescence

PC_CR_NIVEAU

40

Pourcentage de création de niveau  

0=toujours / 100=jamais

40 est une valeur moyenne

BLOC

1 Mo

Taille de bloc en octets pour la création de fichiers

MAX_BLOC

5

Taille maximum générée aléatoirement pour...

Graphique d’utilisation d’un serveur sur un mois

Ce qui est bien avec Linux, et Unix en général, c’est la possibilité que l’on a de trouver des solutions à des problèmes courants, voire même complexes, avec les outils de base.

Voici comment prodiguer de bons conseils, basés sur une démarche scientifique avec graphique à l’appui. Généralement, cela rassure le client, qu’il soit compétent informatiquement parlant ou non. Le but n’est pas de le tromper ou de l’endormir, mais de fournir une analyse scientifique basée sur des données. 

Bien souvent, quand vous avez proposé une architecture à un client, que vous l’avez installée, puis mise en production, il arrive que l’être humain s’habitue à des temps de réponse. Et après quelques jours/mois/années d’exploitation, cet être humain peut devenir excessivement sensible au moindre écart sur des opérations quotidiennes. Chez certains, cela déclenche l’angoisse du "problème de performance".

Généralement, la discussion est de ce style :

<driiiinnnng>

<moi> Bonjour, que puis-je faire pour vous aider ?

<client> J’ai un problème de performance.

<moi> Ah ? Et qu’est-ce qui est lent ?

<client> Tout.

(Cliquetis de frappe sur le clavier...)

<moi> Attendez, je me connecte… mais non, je ne vois rien de spécialement lent.

<client> Si, si, je vous assure, et pourtant je suis sûr que l’on n’a rien changé depuis longtemps, ni fait de mise à jour.

<moi> Déjà, sachez-le, il y a quelque chose qui change... TOUS les jours.

<client> Ah bon ? Mais quoi ?

<moi> Le volume des données… et plus il y a de volume, plus cela peut ralentir l’exploitation globale.

Mais bon, c’est un phénomène normal. Je vais récupérer les statistiques d’utilisation de votre serveur et nous pourrons faire le point.

Je vous rappelle.

<Raccroche>

Et là, pour valider le côté scientifique de votre démarche, rien ne vaut un magnifique graphique issu des statistiques de SAR (System Activity Report), bien présenté...

psutil analyse des informations des processus

Voici un script qui permet de stocker dans une base de données les informations sur les processus.

Dans certains cas, il peut être intéressant de figer les informations pour une analyse ultérieure.

C’est le but de proc2db.py, qui va récolter les informations sur les processus en cours.

Cependant, pour obtenir certaines informations, il faut être ’root’. Et quand on utilise une commande sudo ou su, on perd l’environnement virtuel avec l’interpréteur Python.

La technique consiste à lancer une commande ’sudo bash’ puis à sourcer le script ’activate’ de l’environnement nécessaire pour enfin exécuter le script en mode "super user".

Exemple

$ sudo bash 
# source /home/chris/.virtualenvs/<environnement>/bin/activate 

Le script est plutôt simpliste, il s’agit juste de la déclaration d’une base de données avec SQLAlchemy, puis de la définition de tables pouvant contenir toutes les informations que peut fournir le module psutil.

La table principale est la table PROC, qui contient les informations de base des processus.

Ensuite viennent les tables secondaires :

CPUTIME

Le détail de l’utilisation du CPU pour ce processus

MEMORY

Le détail de la mémoire utilisée pour ce processus

OPENFILE

Les fichiers ouverts par ce processus

PIO

Les statistiques d’entrées/sorties du processus

THREADS

Le détail des threads pour ce processus

Voici le script :

## ================================================== 
## Utilisation de SQL Alchemy + PSUTIL 
## ================================================== 
 
import os 
import sys 
 
from sqlalchemy import sql 
from sqlalchemy import Column, ForeignKey 
from sqlalchemy import Integer, String, DateTime, Date, Numeric, 
BigInteger, Float 
from sqlalchemy import Text 
from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy.orm import relationship 
from sqlalchemy import create_engine 
from sqlalchemy.orm import sessionmaker 
 
import datetime 
import random 
# fichier : psutil/proc2db/proc2db.py 
 
import csv 
 
import psutil 
 
 
## =============================== 
## Creation BASE...

Test continu de débit sur un accès Internet

De nos jours, difficile de se passer d’un accès Internet, cela devient aussi indispensable que l’électricité et le téléphone.

Alors qu’il n’y pas si longtemps, pour passer un coup de téléphone, il fallait se rendre à la poste du village où des cabines étaient prévues à cet usage.

Mais revenons à nos octets : nos FAI (Fournisseurs d’Accès Internet) proposent maintenant des débits allant de 300 Mb/s à 1 Gb/s ( Méga et Giga Bits par seconde).

Attention, 100 Mb/s est la valeur théorique de transfert et il s’agit de bits par seconde qu’il faut donc diviser par 8 pour obtenir des Mo/s (Méga octets par seconde).

300 Mb/s       = 37,5 Mo/s   
1 Gb/s         = 125 Mo/s 

Là aussi, entre les puissances de 10 (1000) et les puissances de 2 (1024), il y a de quoi jouer sur les chiffres.

Sans compter que ce débit reste théorique et n’est valable que jusqu’au matériel de l’opérateur, le téléchargement d’une image ISO sur le site d’une distribution Linux passe par le maillage du réseau des réseaux et une partie du transfert échappe par conséquent à l’opérateur.

Mais comme ses concurrents, il doit garantir l’égalité de traitement et d’acheminement de tout les flux Internet quel que soit son émetteur ou destinataire, c’est ce que l’on appelle la neutralité du net.

Plus d’informations sur le site de l’ARCEP (https://www.arcep.fr/nos-sujets/la-neutralite-du-net.html) qui est, en France, l’autorité chargée de veiller sur le respect de la neutralité du net.

Extrait du site de l’ARCEP :

« Partant du constat qu’Internet est un espace de liberté d’expression, de communication, de liberté d’accès au savoir et de partage, mais aussi de liberté d’entreprise et d’innovation, l’émergence du concept de neutralité du net a pour objectif de protéger l’exercice de ces libertés. »

Cette notion de neutralité fait partie des fondations d’Internet...

Évolution de l’espace disque

Voici un petit utilitaire pour conserver l’utilisation de l’espace disque pour plusieurs répertoires, comme par exemple un /home avec quelques utilisateurs.

Le but est de stocker par utilisateur le volume de données mais aussi le nombre de fichiers.

Un répertoire contenant 1 million de petits fichiers de 1 ko est beaucoup plus long à sauvegarder qu’un seul fichier de 1 Go.

Là aussi, la librairie RRDTOOL peut nous aider pour stocker toutes ces informations.

Obtenir la liste des répertoires situés dans le répertoire /home est facile avec des modules comme path.

Exemple

users = [ str(u.name) for u in Path(HOMES).listdir() ]   

u.name donne le nom du répertoire sans le répertoire parent.

Path( PARENT ).listdir() donne les fichiers et sous-répertoires du répertoire PARENT.

Ceci fait, il suffira de lancer une fonction de chaque occurrence de cette liste, pour obtenir le volume et le nombre de fichiers.

Le volume :

Il y a plusieurs manières de récupérer le volume d’un répertoire, et l’utilisation de la fonction subprocess.run() en est une.

Cela permet de lancer un sous-processus shell avec la commande du (disk usage) et les paramètres sm pour obtenir la valeur en Mo.

proc = run(['du', '-sm', home_user], capture_output=True, text=True)  
size = proc.stdout.split()[0] 

Le nombre de fichiers :

Quant au nombre de fichiers, sans les répertoires, il suffit d’utiliser walkfiles du module path pour parcourir un répertoire de manière récursive.

      p = Path( home_user )  
   nb= 0  
   for l in p.walkfiles(errors='ignore'):  
       if l.isfile():  
           nb += 1 

Voilà pour les fonctions principales et maintenant voici le script :

#fichier: watch_du.py  
  
from path import Path  
from subprocess import run  
import rrdtool  
import datetime  
import time  
  
## --------------------------------------------  
## Recupère la date et l'heure au format epoch  
## --------------------------------------------  ...

Exécution de requête SQL sur un serveur distant

Cet exemple sera difficile à reproduire, mais il correspond à un cas réel et illustre bien l’utilité de savoir scripter en shell et en Python.

Même si ce ne sont pas les plus aboutis et les plus optimisés des scripts, ils sont en adéquation avec le volume de données concernées et la fréquence d’utilisation.

Voici le contexte :

Il y a quelques années, un ERP devait communiquer avec une base MySQL distante, de manière à pouvoir alimenter et rafraîchir régulièrement les données (produits, tarifs...) du site de commerce en ligne.

Il a suffi d’installer le client mysql et ainsi, depuis l’ERP, les développeurs pouvaient lancer simplement des requêtes à destination de la base MySQL.

Un script shell avait d’ailleurs été écrit pour simplifier la vie aux développeurs, et cela centralisait et simplifiait la gestion de l’authentification vis-à-vis de la base distante.

Cela permettait de masquer la complexité de la procédure de connexion à la base de données et ils devaient juste créer un fichier contenant la requête et lancer le shell avec comme argument le fichier de la requête.

mysql_ssh.sh FICHIER_CONTENANT_UNE_REQUETE.sql 

Le résultat apparaissait dans la sortie standard et les erreurs dans la sortie d’erreur, application du principe KISS d’unix (Keep it Simple stupid : restons simple).

Puis, pour des raisons évidentes de sécurité, il a bien fallu protéger cette base de données MySQL derrière un protocole chiffré et sécurisé comme SSH.

Lors de la mise en place de cette mesure de sécurité, mes collègues développeurs furent soulagés de savoir qu’il suffisait de modifier le script. Sinon, ils auraient dû rechercher et modifier les multiples traitements qui faisaient appel à ce script. Car, comme bien trop souvent, aucun développeur n’avait eu l’idée de factoriser le code de lancement de ce script pour en faire une fonction ou une sous-routine, le copier/coller étant tellement plus pratique...

Globalement, le script fonctionnait de la manière suivante :

  • Vérification...

Améliorer Apache Index Of

Dans une petite structure, bien souvent, la répartition des tâches est plus souple que dans un gros service informatique. Dès lors, la mise à disposition ou la gestion des médias d’installation revient aux personnes qui sont chargées de les installer.

Heureusement, maintenant, il suffit de télécharger les fichiers ISO équivalents des DVD et CD-ROM d’il y a quelques années.

Mais dans une petite structure éclatée en différentes entités, le mieux est de mettre à disposition un petit site servi par Apache, pour que tout un chacun puisse se servir en fonction de ses besoins.

De nombreux hébergeurs proposent pour un coût dérisoire un espace et une interface pour gérer des domaines et sous-domaines très simplement.

Mais, un Apache par défaut, fournit une interface comme celle-ci :

images/16EI02.png

Index Of Standard

C’est fonctionnel, mais maintenant que l’on connaît Python, on devrait pouvoir faire mieux.

1. WSGI

Tout d’abord, nous aurions voulu créer un script CGI (Common Gateway Interface) en Python, mais ce n’était pas franchement au goût du jour.

Aujourd’hui, il existe beaucoup de GI (Gateway Interface), dont une pour le langage Python.

L’hébergeur (O2SWITCH, https://www.o2switch.fr/), bien que spécialisé en PHP, propose de déclarer une interface WSGI sur un sous-domaine.

La Web Server Gateway Interface (WSGI) est une spécification qui définit une interface entre des serveurs et des applications web pour le langage Python (source : https://fr.wikipedia.org/wiki/Web_Server_Gateway_Interface).

Pour simplifier, il s’agit d’une interface standardisée avec une application Python qui s’attend à recevoir un objet python pour la requête et doit fournir un objet python pour la réponse.

Le tout est orchestré (chez cet hébergeur) par ’Phusion Passenger server’, un serveur d’applications web open source. Il gère les requêtes HTTP, les processus, les ressources, et permet l’administration, la surveillance et le diagnostic.

C’est parfait, il suffit de déterminer dans l’interface Cpanel (une interface standard pour hébergeur) les paramètres suivants :...

Résumé

Soyez certain que trouver des exemples n’est pas chose aisée. En tant qu’auteur de ces lignes, il a fallu puiser dans ce qui était amusant, ce qui nous a rendu service et ce qui pourrait nous servir.

Tous sont des exemples originaux, que nous avons pris plaisir à écrire ou à réécrire en Python.

Coder est un formidable espace de jeu. De plus, avec un outil comme Internet, il est facile de trouver une solution aux problèmes qui se présentent en cours de développement ou de mise au point.

Et n’oubliez pas la célèbre devise Shadok : « S’il n’y a pas de solution, c’est qu’il n’y a pas de problème. »