En tant que sysadmin, l'automatisation est votre meilleur allié. Tandis que Bash excelle pour les tâches simples et les pipes de commandes, Python offre une puissance considérable pour les scripts complexes, la gestion des erreurs et l'intégration API. Ce guide couvre les bibliothèques essentielles et des cas d'usage concrets pour automatiser votre infrastructure.
Plan du guide
- Pourquoi Python plutôt que Bash ? — Comparaison et quand choisir quoi
- Les bibliothèques essentielles — Paramiko, Fabric, psutil, requests, Jinja2
- Scripts pratiques — Inventaire serveurs, monitoring, intégration API
- Structurer ses scripts — Argparse, logging, gestion d'erreurs
- Perspectives et évolutions
Pourquoi Python plutôt que Bash ?
Les deux ont leur place. Bash brille pour les tâches ponctuelles et l'intégration native de commandes système. Python devient indispensable quand vous avez besoin de logique métier, d'API, de structure et de maintenabilité.
Comparaison pratique
| Critère | Python | Bash |
| Logique complexe | ✅ Excellent | ❌ Lourd |
| Gestion d'erreurs | ✅ Structurée | ⚠️ Manuelle |
| Appels API | ✅ Natif (requests) | ❌ curl + parsing |
| Traitement données | ✅ Dictionnaires, listes | ⚠️ Chaînes/regex |
| One-liners | ⚠️ Verbeux | ✅ Agile |
| Pipes commandes | ⚠️ Laborieux | ✅ Naturel |
| Déploiement SSH | ✅ Fabric | ⚠️ scp + bash |
| Portabilité | ✅ macOS, Linux, Windows | ⚠️ Bash différent par OS |
Cas Python : Inventaire serveurs, monitoring avec métriques, déploiement automatisé, ETL logs, intégration API. Cas Bash : One-liners, pipes simples, tests conditionnels rapides, scripts système légers.
Les bibliothèques essentielles
| Bibliothèque | Usage | Exemple |
| paramiko | SSH/SFTP bas niveau | Connexion serveur, exécution commande |
| fabric | SSH déploiement haut niveau | Orchestration multi-serveurs |
| psutil | Monitoring système | CPU, mémoire, disque, processus |
| subprocess | Exécution commandes système | Wrapper secure de shell |
| requests | Requêtes HTTP/API | REST API, webhook |
| jinja2 | Templating | Config provisioning |
| pathlib | Manipulation fichiers | Chemins cross-platform |
| argparse | CLI arguments | Script CLI robuste |
| logging | Logs structurés | Traçabilité debug |
| json/yaml | Sérialisation config | Parsing/dumping configs |
Script 1 : Inventaire serveurs avec Paramiko
Collectez les infos système sur plusieurs serveurs.
import paramiko
import csv
from pathlib import Path
def ssh_exec(hostname, username, key_path, command):
"""Exécute une commande sur un serveur via SSH"""
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname, username=username, key_filename=key_path, timeout=10)
stdin, stdout, stderr = ssh.exec_command(command)
result = stdout.read().decode().strip()
ssh.close()
return result
def inventory_servers(servers_file):
"""Collecte l'inventaire de tous les serveurs"""
inventory = []
with open(servers_file) as f:
servers = [line.strip() for line in f if line.strip()]
for hostname in servers:
try:
uptime = ssh_exec(hostname, 'admin', '~/.ssh/id_rsa', 'uptime')
disk = ssh_exec(hostname, 'admin', '~/.ssh/id_rsa', 'df -h / | tail -1 | awk \'{print $5}\'')
kernel = ssh_exec(hostname, 'admin', '~/.ssh/id_rsa', 'uname -r')
inventory.append({
'hostname': hostname,
'uptime': uptime,
'disk_usage': disk,
'kernel': kernel
})
except Exception as e:
print(f"Erreur {hostname}: {e}")
# Sauvegarde en CSV
with open('inventory.csv', 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=['hostname', 'uptime', 'disk_usage', 'kernel'])
writer.writeheader()
writer.writerows(inventory)
print(f"Inventaire de {len(inventory)} serveurs sauvegardé")
if __name__ == '__main__':
inventory_servers('servers.txt')
Script 2 : Monitoring système avec psutil
Générez des alertes basées sur les métriques de votre infrastructure.
import psutil
import json
from datetime import datetime
def check_system_health():
"""Vérifie la santé du système et retourne les métriques"""
metrics = {
'timestamp': datetime.now().isoformat(),
'cpu_percent': psutil.cpu_percent(interval=1),
'memory': {
'percent': psutil.virtual_memory().percent,
'used_gb': psutil.virtual_memory().used / (1024**3),
'total_gb': psutil.virtual_memory().total / (1024**3)
},
'disk': {
'percent': psutil.disk_usage('/').percent,
'free_gb': psutil.disk_usage('/').free / (1024**3)
},
'process_count': len(psutil.pids()),
'alerts': []
}
# Alertes
if metrics['cpu_percent'] > 80:
metrics['alerts'].append(f"CPU élevé: {metrics['cpu_percent']}%")
if metrics['memory']['percent'] > 85:
metrics['alerts'].append(f"Mémoire critique: {metrics['memory']['percent']}%")
if metrics['disk']['percent'] > 90:
metrics['alerts'].append(f"Disque presque plein: {metrics['disk']['percent']}%")
return metrics
def send_webhook(metrics, webhook_url):
"""Envoie les métriques à un webhook (ex: monitoring SHPV)"""
import requests
try:
requests.post(webhook_url, json=metrics, timeout=5)
except requests.RequestException as e:
print(f"Erreur webhook: {e}")
if __name__ == '__main__':
health = check_system_health()
print(json.dumps(health, indent=2))
# Optionnel: envoyer à votre système de monitoring
# send_webhook(health, 'https://monitoring.example.com/api/metrics')
Script 3 : Intégration API REST avec requests
Interagissez avec vos APIs d'infrastructure (load balancers, cloud providers, etc).
import requests
import logging
from typing import Optional, Dict, Any
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class APIClient:
def __init__(self, base_url: str, token: str):
self.base_url = base_url
self.headers = {'Authorization': f'Bearer {token}', 'Content-Type': 'application/json'}
def get(self, endpoint: str) -> Optional[Dict[str, Any]]:
"""GET request avec gestion d'erreur"""
try:
response = requests.get(
f"{self.base_url}/{endpoint}",
headers=self.headers,
timeout=10
)
response.raise_for_status()
return response.json()
except requests.RequestException as e:
logger.error(f"Erreur GET {endpoint}: {e}")
return None
def post(self, endpoint: str, data: Dict) -> Optional[Dict[str, Any]]:
"""POST request"""
try:
response = requests.post(
f"{self.base_url}/{endpoint}",
json=data,
headers=self.headers,
timeout=10
)
response.raise_for_status()
return response.json()
except requests.RequestException as e:
logger.error(f"Erreur POST {endpoint}: {e}")
return None
# Usage
if __name__ == '__main__':
client = APIClient('https://api.cloud.example.com', 'your_token_here')
# Récupérer instances
instances = client.get('compute/instances')
if instances:
logger.info(f"Instances trouvées: {len(instances.get('data', []))}")
# Créer une ressource
new_instance = {
'name': 'web-server-01',
'size': 'small',
'region': 'fr-toulouse'
}
result = client.post('compute/instances', new_instance)
Structurer ses scripts
Utiliser argparse pour un CLI robuste
import argparse
import sys
def main():
parser = argparse.ArgumentParser(
description='Outil d\'administration système',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog='Exemples:\n %(prog)s inventory --format csv\n %(prog)s monitor --alert-cpu 80'
)
subparsers = parser.add_subparsers(dest='command', help='Commande')
# Subcommande inventory
inv_parser = subparsers.add_parser('inventory', help='Collecter inventaire')
inv_parser.add_argument('--servers', required=True, help='Fichier serveurs')
inv_parser.add_argument('--format', choices=['csv', 'json'], default='csv')
# Subcommande monitor
mon_parser = subparsers.add_parser('monitor', help='Monitoring temps réel')
mon_parser.add_argument('--alert-cpu', type=int, default=80, help='Seuil CPU %')
mon_parser.add_argument('--interval', type=int, default=5, help='Intervalle secondes')
args = parser.parse_args()
if not args.command:
parser.print_help()
sys.exit(1)
if args.command == 'inventory':
print(f"Inventaire depuis {args.servers} en format {args.format}")
elif args.command == 'monitor':
print(f"Monitoring avec seuil CPU à {args.alert_cpu}%")
if __name__ == '__main__':
main()
Logging structuré
import logging
import logging.handlers
def setup_logging(logfile='app.log', level=logging.INFO):
"""Configure les logs avec rotation"""
logger = logging.getLogger('sysadmin')
logger.setLevel(level)
# Fichier avec rotation
file_handler = logging.handlers.RotatingFileHandler(
logfile, maxBytes=10*1024*1024, backupCount=5
)
# Format structuré
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
return logger
# Usage
logger = setup_logging('sysadmin.log')
logger.info('Script démarré')
logger.warning('Attention: mémoire élevée')
logger.error('Erreur de connexion SSH')
Comparaison avec Bash
Voici les mêmes cas en Bash (souvent plus complexes) :
# Inventaire basique (Bash)
while IFS= read -r host; do
uptime=$(ssh admin@$host uptime 2>/dev/null)
disk=$(ssh admin@$host 'df -h / | tail -1 | awk "{print $5}"' 2>/dev/null)
echo "$host,$uptime,$disk" >> inventory.csv
done < servers.txt
# Monitoring (Bash)
while true; do
cpu=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)
if (( $(echo "$cpu > 80" | bc -l) )); then
echo "ALERTE: CPU à $cpu%"
fi
sleep 5
done
# API avec curl (Bash)
token="your_token"
curl -H "Authorization: Bearer $token" \
-H "Content-Type: application/json" \
https://api.cloud.example.com/compute/instances
Vous voyez : gestion d'erreurs minimale, parsing fragile, moins de portabilité.
Perspectives et apprentissage
Pour approfondir votre automatisation :
- Orchestration : Ansible pour le déploiement multi-serveurs
- Bash avancé : Bash scripting pour les cas légers
- Infrastructure as Code : Terraform, CloudFormation pour l'IaC
Sources
- Documentation Python officielle
- Fabric: SSH deployment in Python
- psutil: cross-platform system monitoring
Conclusion
Python s'est imposé comme le langage de facto pour l'automatisation infrastructure. Ses bibliothèques (paramiko, fabric, psutil, requests) vous permettent d'écrire des scripts robustes, maintenables et portables.
Chez SHPV, l'automatisation de votre infrastructure est essentielle. Que vous orchestriez des serveurs sur nos infrastructures d'hébergement, supervisiez des instances cloud ou intégriez vos APIs monitoring, Python offre la structure et la performance nécessaires.
Commencez par les bibliothèques essentielles, structurez avec argparse et logging, puis évoluez vers des outils comme Fabric pour l'orchestration multi-serveurs.


