Comparatif des scripts d'automatisation en Shell, Python et Go

En Shell, l'affichage se fait via echo ou printf. echo ajoute automatiquement un saut de ligne, tandis que printf permet un formatage précis sans saut de ligne implicite. En Python, la fonction intégrée print() gère l'affichage et supporte les f-strings pour une interpolation élégante. En Golang, le package fmt fournit Println pour un affichage simple avec saut de ligne, et Printf pour le formatage.

# Shell
utilisateur="Jean"
echo "Bonjour le monde!"
echo "Salut, $utilisateur!"
printf "Profil: %s\n" "$utilisateur"

# Python
utilisateur = "Jean"
print("Bonjour le monde!")
print(f"Salut, {utilisateur}!")

// Golang
package main
import "fmt"
func main() {
    utilisateur := "Jean"
    fmt.Println("Bonjour le monde!")
    fmt.Printf("Salut, %s!\n", utilisateur)
}

Lecture d'entrées utilisateur (input)

En Shell, la commande read capte les entrées, avec l'option -p pour le prompt et -s pour masquer la saisie (mots de passe). En Python, input() retourne toujours une chaîne de caractères, nécessitant une conversion explicite pour les nombres ; le module getpass sécurise les saisies. En Golang, fmt.Scan gère les entrées simples, tandis que bufio.NewReader lit des lignes complètes.

# Shell
read -p "Votre nom: " utilisateur
echo "Bienvenue, $utilisateur"
read -s -p "Mot de passe: " mdp

# Python
utilisateur = input("Votre nom: ")
print(f"Bienvenue, {utilisateur}")
from getpass import getpass
mdp = getpass("Mot de passe: ")

// Golang
package main
import (
    "bufio"
    "fmt"
    "os"
)
func main() {
    var utilisateur string
    fmt.Print("Votre nom: ")
    fmt.Scan(&utilisateur)
    fmt.Printf("Bienvenue, %s\n", utilisateur)

    lecteur := bufio.NewReader(os.Stdin)
    fmt.Print("Votre ville: ")
    ville, _ := lecteur.ReadString('\n')
    fmt.Printf("Ville: %s", ville)
}

Indentation et conventions de code

L'indentation est optionnelle en Shell (recommandée pour la lisibilité), obligatoire en Python (fait partie de la syntaxe) et gérée par des tabulations en Go (convention officielle via gofmt).

Langage Nommage des variables Commentaires Structure principale
Shell MAJUSCULES # Shebang + variables + fonctions
Python snake_case # ou """ Imports + constantes + classes + fonctions
Golang camelCase // ou /* */ Package + imports + types + fonctions

Variables et types numériques

Shell traite les nombres comme des chaînes et utilise $(( )) ou bc pour les calculs. Python est dynamiqumeent typé et gère nativement les entiers, flottants et complexes. Go est statiquement typé et propose des types comme int, float64, et complex128.

# Shell
MSG="Bonjour"
valA=15
valB=4
somme=$((valA + valB))

# Python
msg = "Bonjour"
val_a = 15
val_b = 4
somme = val_a + val_b

// Golang
var msg string = "Bonjour"
valA := 15
valB := 4
somme := valA + valB

Chaînes de caractères, index et slicing

Le slicing permet d'extraire des sous-chaînes. Shell utilise ${var:debut:longueur}, Python et Go utilisent la syntaxe [debut:fin].

# Shell
txt="Automatisation"
echo ${#txt}          # Longueur: 14
echo ${txt:0:4}       # Auto

# Python
txt = "Automatisation"
print(len(txt))       # 14
print(txt[0:4])       # Auto

// Golang
txt := "Automatisation"
fmt.Println(len(txt)) // 14
fmt.Println(txt[0:4]) // Auto

Expressions régulières

Shell s'appuie sur des outils externes comme grep, sed et awk. Python utilise le module re, et Go le package regexp avec des fonctions comme MustCompile et FindString.

# Shell
echo "test123" | grep -Eo "[0-9]+"

# Python
import re
resultat = re.search(r"[0-9]+", "test123")
print(resultat.group())

// Golang
package main
import (
    "fmt"
    "regexp"
)
func main() {
    re := regexp.MustCompile(`[0-9]+`)
    fmt.Println(re.FindString("test123"))
}

Connexion aux bases de données (MySQL / PostgreSQL)

Python utilise des librairies comme mysql-connector-python et psycopg2 avec un curseur pour exécuter les requêtes. Go s'appuie sur database/sql avec des drivers spécifiques comme go-sql-driver/mysql et lib/pq.

# Python (MySQL)
import mysql.connector
conn = mysql.connector.connect(host="localhost", user="root", password="pwd", database="mabase")
cur = conn.cursor()
cur.execute("SELECT * FROM clients")
for ligne in cur.fetchall():
    print(ligne)
cur.close()
conn.close()

// Golang (PostgreSQL)
package main
import (
    "database/sql"
    "fmt"
    _ "github.com/lib/pq"
)
func main() {
    db, err := sql.Open("postgres", "user=postgres password=pwd dbname=mabase sslmode=disable")
    if err != nil { panic(err) }
    defer db.Close()
    lignes, _ := db.Query("SELECT * FROM clients")
    for lignes.Next() {
        var id int
        var nom string
        lignes.Scan(&id, &nom)
        fmt.Println(id, nom)
    }
}

Concurrence et Multi-processus

Shell lance des processus en arrière-plan avec & et attend avec wait. Python utilise le module multiprocessing avec une classe Pool ou Process. Go excelle dans ce domaine avec les goroutines et les channels, synchronisés via sync.WaitGroup.

# Python
from multiprocessing import Process
def tache(nom):
    print(f"Tâche {nom} en cours")
if __name__ == "__main__":
    processus = []
    for i in range(3):
        p = Process(target=tache, args=(f"Proc-{i}",))
        processus.append(p)
        p.start()
    for p in processus:
        p.join()

// Golang
package main
import (
    "fmt"
    "sync"
)
func tache(wg *sync.WaitGroup, nom string) {
    defer wg.Done()
    fmt.Printf("Tâche %s en cours\n", nom)
}
func main() {
    var wg sync.WaitGroup
    for i := 1; i <= 3; i++ {
        wg.Add(1)
        go tache(&wg, fmt.Sprintf("Proc-%d", i))
    }
    wg.Wait()
}

Threads et Verrous (Mutex)

En Python, les threads se gèrent avec threading.Thread et la synchronisation via threading.Lock. En Go, on utilise des goroutines pour la concurrence et sync.Mutex pour protéger les ressources partagées. Les deadlocks peuvent être évités en évitant les locks imbriqués ou en utilisant des channels.

# Python
import threading
compteur = 0
verrou = threading.Lock()
def incrementer():
    global compteur
    with verrou:
        compteur += 1

// Golang
package main
import (
    "fmt"
    "sync"
)
var (
    compteur int
    verrou   sync.Mutex
)
func incrementer(wg *sync.WaitGroup) {
    defer wg.Done()
    verrou.Lock()
    compteur++
    verrou.Unlock()
}

Gestion des exceptions et erreurs

Python utilise try...except...finally pour capturer les erreurs. Go privilégie le retour d'erreurs explicite, mais gère les paniques avec defer et recover. Shell capture les signaux et erreurs avec trap.

# Python
try:
    x = 1 / 0
except ZeroDivisionError as e:
    print(f"Erreur: {e}")
finally:
    print("Nettoyage")

// Golang
func main() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Récupéré:", r)
        }
    }()
    panic("Erreur critique")
}

# Shell
trap 'echo "Erreur interceptée"; exit 1' ERR
ls /dossier_inexistant

Automatisation Docker via l'API et les SDK

L'API Docker Engine permet de gérer les conteneurs via des requêtes HTTP sur le port 2375 (ou 2376 avec TLS). Les langages proposent des SDK officiels pour interagir programmatiquement sans appeler curl ou le CLI Docker.

Appels API directs (cURL)

# Lister les conteneurs
curl "http://localhost:2375/containers/json"

# Créer un conteneur Nginx
curl -X POST "http://localhost:2375/containers/create" \
     -H "Content-Type: application/json" \
     -d '{"Image": "nginx", "HostConfig": {"PortBindings": {"80/tcp": [{"HostPort": "8080"}]}}}'

Python avec le SDK Docker

import docker
client = docker.DockerClient(base_url='tcp://localhost:2375')
client.images.pull('nginx')
conteneur = client.containers.run('nginx', detach=True, ports={'80/tcp': 8080})
print(conteneur.name)
conteneur.stop()
conteneur.remove()

Golang avec le SDK Docker

package main
import (
    "context"
    "fmt"
    "github.com/docker/docker/api/types"
    "github.com/docker/docker/client"
)
func main() {
    cli, _ := client.NewClientWithOpts(client.FromEnv)
    _, _ = cli.ImagePull(context.Background(), "nginx", types.ImagePullOptions{})
    fmt.Println("Image Nginx prête")
    // Gestion des conteneurs, réseaux, volumes...
}

Gestion système de Docker

L'API Docker permet de récupérer des métriques systèmes, des logs, ou de gérer les réseaux et volumes via des endpoints dédiés comme /info, /containers/{id}/stats, ou /volumes/create.

# Récupérer l'utilisation des ressources d'un conteneur
curl "http://localhost:2375/containers/<id>/stats"

# Créer un volume nommé
curl -X POST "http://localhost:2375/volumes/create" \
     -H "Content-Type: application/json" \
     -d '{"Name": "mon_volume"}'

Étiquettes: Shell Python golang automatisation Docker

Publié le 25 juin à 06h05