jq est le processeur JSON en ligne de commande que chaque administrateur Linux et ingénieur DevOps devrait avoir dans sa boîte à outils. Que vous travailliez avec des API REST, analysiez la sortie de Kubernetes, traitiez l’état Terraform ou extrayiez des données de fichiers journaux, jq vous permet de découper, filtrer et transformer du JSON directement depuis le terminal — sans avoir besoin d’un script Python.
Ce guide couvre tout, de l’extraction de champs basique aux transformations avancées, avec des exemples concrets que vous utiliserez quotidiennement.
Prérequis
- Un système Linux (n’importe quelle distribution)
- Familiarité de base avec les pipes shell et les outils en ligne de commande
- Des données JSON avec lesquelles travailler (nous utiliserons des exemples tout au long du guide)
Installer jq
Sur Debian/Ubuntu :
sudo apt update && sudo apt install -y jq
Sur RHEL/Fedora/AlmaLinux :
sudo dnf install -y jq
Sur Alpine :
sudo apk add jq
Sur macOS :
brew install jq
Vérification :
jq --version
jq vs Autres Outils de Traitement JSON
| Outil | Idéal Pour | Inconvénients |
|---|---|---|
| jq | Transformations CLI rapides, pipes shell | La logique complexe devient verbeuse |
| Python json | Traitement multi-étapes, logique complexe | Nécessite l’environnement Python, plus de code |
| yq | Traitement YAML (syntaxe type jq) | Installation séparée, spécifique YAML |
| fx | Exploration interactive de JSON | Non scriptable |
| gron | Rendre JSON greppable | Unidirectionnel (aplatissement uniquement) |
jq l’emporte lorsque vous avez besoin de transformations rapides et scriptables dans un pipeline sans aucune dépendance au-delà du binaire.
jq Basique : Extraction de Données
Le Filtre Identité
L’opération jq la plus simple embellit l’affichage du JSON :
echo '{"name":"nginx","version":"1.25.3","status":"running"}' | jq '.'
{
"name": "nginx",
"version": "1.25.3",
"status": "running"
}
Extraction de Champs
Utilisez la notation par points pour extraire des valeurs spécifiques :
echo '{"name":"nginx","version":"1.25.3","status":"running"}' | jq '.name'
"nginx"
Pour obtenir la chaîne brute sans guillemets, ajoutez -r :
echo '{"name":"nginx","version":"1.25.3"}' | jq -r '.name'
nginx
Le flag
-rest essentiel pour les scripts. Sans lui, jq produit des chaînes encodées JSON (avec guillemets), ce qui casse les assignations de variables et les comparaisons dans bash.
Objets Imbriqués
echo '{"server":{"host":"10.0.0.1","port":8080}}' | jq '.server.port'
8080
Accès aux Tableaux
echo '["nginx","apache","caddy"]' | jq '.[0]'
"nginx"
Obtenir tous les éléments :
echo '["nginx","apache","caddy"]' | jq '.[]'
"nginx"
"apache"
"caddy"
Travailler avec de Vraies Réponses d’API
Voici un scénario réaliste : interroger une API REST et extraire ce dont vous avez besoin.
# Obtenir les infos utilisateur GitHub
curl -s https://api.github.com/users/torvalds | jq '{login, name, public_repos, followers}'
{
"login": "torvalds",
"name": "Linus Torvalds",
"public_repos": 7,
"followers": 223000
}
Extraction depuis des Tableaux d’Objets
La plupart des API retournent des tableaux. Voici comment travailler avec eux :
# Simuler une réponse d'API
cat << 'EOF' | jq '.servers[] | {name, status}'
{
"servers": [
{"name": "web-01", "status": "running", "cpu": 45},
{"name": "web-02", "status": "stopped", "cpu": 0},
{"name": "db-01", "status": "running", "cpu": 78}
]
}
EOF
{
"name": "web-01",
"status": "running"
}
{
"name": "web-02",
"status": "stopped"
}
{
"name": "db-01",
"status": "running"
}
Filtrer des Données JSON avec jq
La Fonction select()
Filtrer les tableaux pour ne garder que les éléments correspondants :
cat << 'EOF' | jq '.servers[] | select(.status == "running")'
{
"servers": [
{"name": "web-01", "status": "running", "cpu": 45},
{"name": "web-02", "status": "stopped", "cpu": 0},
{"name": "db-01", "status": "running", "cpu": 78}
]
}
EOF
{
"name": "web-01",
"status": "running",
"cpu": 45
}
{
"name": "db-01",
"status": "running",
"cpu": 78
}
Comparaisons Numériques
# Serveurs avec utilisation CPU supérieure à 50%
cat servers.json | jq '.servers[] | select(.cpu > 50) | .name'
Combiner des Conditions
# Serveurs en cours d'exécution avec CPU élevé
cat servers.json | jq '.servers[] | select(.status == "running" and .cpu > 50)'
Correspondance de Chaînes
# Serveurs dont le nom contient "web"
cat servers.json | jq '.servers[] | select(.name | contains("web"))'
Pour la correspondance regex :
# Noms correspondant à un motif
cat servers.json | jq '.servers[] | select(.name | test("web-[0-9]+"))'
Transformer du JSON avec jq
Construire de Nouveaux Objets
Construire de nouvelles structures JSON à partir de données existantes :
cat << 'EOF' | jq '.servers[] | {hostname: .name, healthy: (.status == "running"), load: (.cpu / 100)}'
{
"servers": [
{"name": "web-01", "status": "running", "cpu": 45},
{"name": "db-01", "status": "running", "cpu": 78}
]
}
EOF
{
"hostname": "web-01",
"healthy": true,
"load": 0.45
}
{
"hostname": "db-01",
"healthy": true,
"load": 0.78
}
map() pour les Transformations de Tableaux
Transformer chaque élément d’un tableau :
echo '[1,2,3,4,5]' | jq 'map(. * 2)'
[2, 4, 6, 8, 10]
Exemple pratique — extraire uniquement les noms dans un tableau :
cat servers.json | jq '[.servers[].name]'
["web-01", "web-02", "db-01"]
Tri et Regroupement
# Trier par CPU décroissant
cat servers.json | jq '.servers | sort_by(.cpu) | reverse'
# Regrouper par statut
cat servers.json | jq '.servers | group_by(.status)'
Agrégations
# Compter les serveurs
cat servers.json | jq '.servers | length'
# CPU moyen
cat servers.json | jq '.servers | map(.cpu) | add / length'
# CPU maximum
cat servers.json | jq '.servers | max_by(.cpu) | .name'
jq dans les Scripts Shell
Stocker des Résultats dans des Variables
#!/bin/bash
response=$(curl -s https://api.github.com/users/torvalds)
name=$(echo "$response" | jq -r '.name')
repos=$(echo "$response" | jq -r '.public_repos')
echo "User: $name has $repos public repos"
Attention : Utilisez toujours des guillemets autour de la variable dans
echo "$response". Les variables non quotées perdent les espaces blancs et cassent l’analyse JSON.
Itérer sur des Tableaux JSON
#!/bin/bash
# Traiter chaque serveur depuis l'API
curl -s https://api.example.com/servers | jq -r '.[] | .name' | while read -r server; do
echo "Checking $server..."
ping -c 1 -W 2 "$server" > /dev/null 2>&1 && echo " UP" || echo " DOWN"
done
Générer des Fichiers de Configuration depuis JSON
# Convertir l'inventaire JSON en entrées /etc/hosts
cat inventory.json | jq -r '.hosts[] | "\(.ip)\t\(.hostname)"' >> /etc/hosts
Traitement Conditionnel
#!/bin/bash
status=$(curl -s https://api.example.com/health | jq -r '.status')
if [ "$status" != "healthy" ]; then
echo "ALERT: Service is $status" | mail -s "Health Check Failed" admin@example.com
fi
Modifier du JSON avec jq
Mettre à Jour des Valeurs
echo '{"version": "1.0", "debug": false}' | jq '.version = "2.0" | .debug = true'
{
"version": "2.0",
"debug": true
}
Ajouter des Champs
echo '{"name": "app"}' | jq '. + {"env": "production", "replicas": 3}'
Supprimer des Champs
echo '{"name":"app","secret":"abc123","version":"1.0"}' | jq 'del(.secret)'
Mettre à Jour des Valeurs Imbriquées
echo '{"database":{"host":"old-host","port":5432}}' | jq '.database.host = "new-host"'
Recettes jq du Monde Réel
Analyser le Statut des Pods Kubernetes
kubectl get pods -o json | jq -r '.items[] | select(.status.phase != "Running") | "\(.metadata.name)\t\(.status.phase)"'
Extraire les Valeurs de Sortie Terraform
terraform output -json | jq -r 'to_entries[] | "\(.key) = \(.value.value)"'
Analyser les Statistiques de Conteneurs Docker
docker inspect $(docker ps -q) | jq '.[] | {name: .Name, ip: .NetworkSettings.IPAddress, status: .State.Status}'
Traiter les Entrées de Journal CloudWatch
aws logs get-log-events --log-group-name /app/prod --log-stream-name main \
| jq -r '.events[] | "\(.timestamp | . / 1000 | strftime("%Y-%m-%d %H:%M:%S")) \(.message)"'
Sortie CSV depuis JSON
cat servers.json | jq -r '.servers[] | [.name, .status, (.cpu | tostring)] | @csv'
"web-01","running","45"
"web-02","stopped","0"
"db-01","running","78"
Résolution de Problèmes
“parse error: Invalid numeric literal” : Votre entrée n’est pas du JSON valide. Validez-la d’abord avec jq '.' file.json. Cause courante : l’API a retourné du HTML (page d’erreur) au lieu de JSON.
Sortie “null” alors que vous attendez des données : Le nom du champ est incorrect ou n’existe pas à ce chemin. Utilisez jq 'keys' pour voir les champs disponibles, ou jq '.' | head -20 pour inspecter la structure.
Guillemets dans les assignations de variables : Utilisez toujours jq -r (sortie brute) lors de l’assignation à des variables shell. Sans cela, vous obtenez "value" au lieu de value, ce qui casse les comparaisons de chaînes.
“Cannot iterate over null” : Vous essayez d’itérer (.[]) sur un champ qui est null ou manquant. Ajoutez l’opérateur optionnel : .field[]? ou vérifiez avec select(. != null).
Problèmes d’espaces blancs dans les pipes : Quotez vos variables. echo $json | jq '.' casse sur les espaces blancs. Utilisez plutôt echo "$json" | jq '.'.
Résumé
- jq est l’outil standard pour le traitement JSON en ligne de commande — un binaire, pas de dépendances, fonctionne partout
- Utilisez
.field,.[index]et.[]pour l’extraction de base ; ajoutez-rpour une sortie de chaîne brute dans les scripts select()filtre les tableaux par condition — prend en charge la correspondance de chaînes, les comparaisons numériques et les regex avectest()- Construisez de nouvelles structures JSON avec la construction d’objets
{key: .field}etmap()pour les transformations de tableaux - Combinez avec
curl,kubectl,terraformetdockerpour l’automatisation en conditions réelles sort_by(),group_by(),length,addgèrent le tri et l’agrégation- Modifiez le JSON avec l’assignation (
.key = value), l’addition (. + {}), et la suppression (del(.key)) - Utilisez toujours le flag
-ret quotez les variables lors de l’intégration de jq dans des scripts bash
Bash Scripting for Sysadmins: The Essential Guide | Install Security Updates from the Command Line in Ubuntu