Scripting af cloudressourcer via CLI og jq
Styr cloududbyderes CLI'er idempotent, og fortolk JSON-svar for at oprette og nedlægge ressourcer.
Scripting af cloudressourcer via CLI og jq er en gratis Linux-kommandolinjen og Bash-scripting på ekspertniveau-lektion på CoddyKit. Dette er lektion 3 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Linux-kommandolinjen og Bash-scripting på ekspertniveau, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Linux-kommandolinjen og Bash-scripting på ekspertniveau-kurset indeholder 4 lektioner i alt.
Hvorfor idempotent scripting i skyen er vigtigt
På C2-niveau handler scripting i skyen ikke om at klikke på knapper — det handler om at skrive kode, der kan køres sikkert flere gange uden at oprette duplikerede ressourcer eller fejle ved den anden kørsel.
Et idempotent script kontrollerer, om en ressource allerede findes, før den oprettes. Det er grundstenen i pålidelig automatisering af infrastruktur.
- CLI-værktøjer til skytjenester (AWS, GCP, Azure) returnerer JSON — det er afgørende at kunne fortolke dette output.
jqer standardværktøjet i Unix til at udvælge, filtrere og omforme JSON fra shell-scripts.- Ved at kombinere CLI, jq og betinget logik kan du skrive robuste, gentagelige scripts til klargøring.
Gennem hele denne lektion klargør du S3-buckets, EC2-instanser og IAM-roller med AWS CLI som reference, ved hjælp af mønstre, der kan overføres direkte til gcloud og az.
Installation og kontrol af CLI-værktøjer til skytjenester
Før du scripter, skal du bekræfte, at de rigtige værktøjer er til stede. Lås altid versioner fast i CI for at undgå forskelle mellem miljøer.
Udsnittet nedenfor kontrollerer, om AWS CLI v2, jq og GCP SDK'et er installeret, og installerer kun det, der mangler — et mønster, der er nyttigt i bootstrap-scripts til nye VM'er eller containere.
#!/usr/bin/env bash
set -euo pipefail
check_or_install() {
local cmd="$1"
local install_cmd="$2"
if ! command -v "$cmd" &>/dev/null; then
echo "[INFO] $cmd not found — installing..."
eval "$install_cmd"
else
echo "[OK] $cmd $("$cmd" --version 2>&1 | head -1)"
fi
}
# AWS CLI v2
check_or_install aws \
'curl -fsSL https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip -o /tmp/awscliv2.zip && unzip -q /tmp/awscliv2.zip -d /tmp && sudo /tmp/aws/install'
# jq
check_or_install jq \
'sudo apt-get install -y jq 2>/dev/null || sudo yum install -y jq'
# gcloud (optional)
check_or_install gcloud \
'echo "Install gcloud SDK manually from https://cloud.google.com/sdk"'
echo "All prerequisites satisfied."Forespørgsel efter eksisterende ressourcer med jq
Det første trin i ethvert idempotent script er en læsning — spørg API'et, om ressourcen allerede findes, og vælg derefter den relevante gren.
AWS CLI returnerer altid JSON. jq lader dig udtrække præcis det felt, du har brug for:
jq -r '.Buckets[].Name'— rå tekstoutput med ét bucketnavn pr. linje.jq -e— afslutter med kode 1, hvis udtrykket givernullellerfalse, hvilket gør det velegnet tilif-betingelser.jq '.[] | select(.Name == env.BUCKET)'— filtrér ved hjælp af en shell-variabel viaenv.
Udsnittet nedenfor viser alle S3-buckets og kontrollerer, om en bestemt bucket allerede findes.
#!/usr/bin/env bash
set -euo pipefail
BUCKET="my-devops-artifacts-$(date +%Y%m)"
echo "Fetching existing S3 buckets..."
EXISTING=$(aws s3api list-buckets --output json)
# Extract names as newline-separated list
echo "$EXISTING" | jq -r '.Buckets[].Name'
# Check if target bucket exists
if echo "$EXISTING" | jq -e --arg b "$BUCKET" '.Buckets[] | select(.Name == $b)' > /dev/null 2>&1; then
echo "[EXISTS] Bucket $BUCKET already present — skipping creation."
else
echo "[MISSING] Bucket $BUCKET not found — will create."
fiIdempotent oprettelse af S3-bucket
Når kontrollen af, om ressourcen findes, er på plads, skal du omslutte oprettelsen med en betingelse. En velformet funktion til skyinfrastruktur følger dette mønster:
- Læs den aktuelle tilstand fra API'et.
- Sammenlign den ønskede tilstand med den faktiske tilstand.
- Udfør kun handlinger for forskellene.
Bemærk flaget --create-bucket-configuration — det er påkrævet i alle regioner undtagen us-east-1. Ved at angive regionen direkte i scriptet undgår du tavse fejl, når AWS_DEFAULT_REGION ikke er sat.
#!/usr/bin/env bash
set -euo pipefail
REGION="eu-west-1"
BUCKET="my-devops-artifacts-$(date +%Y%m)"
ensure_bucket() {
local bucket="$1"
local region="$2"
local existing
existing=$(aws s3api list-buckets --query 'Buckets[].Name' --output json)
if echo "$existing" | jq -e --arg b "$bucket" 'index($b) != null' > /dev/null 2>&1; then
echo "[SKIP] Bucket $bucket already exists."
return 0
fi
echo "[CREATE] Creating bucket $bucket in $region..."
aws s3api create-bucket \
--bucket "$bucket" \
--region "$region" \
--create-bucket-configuration LocationConstraint="$region"
# Enable versioning immediately after creation
aws s3api put-bucket-versioning \
--bucket "$bucket" \
--versioning-configuration Status=Enabled
echo "[DONE] Bucket $bucket created with versioning enabled."
}
ensure_bucket "$BUCKET" "$REGION"Fortolkning af indlejret JSON: EC2-instansens tilstand
EC2-svar er dybt indlejrede. Stiadgang med jq og --query (JMESPath, som er indbygget i AWS CLI) fungerer begge — men jq er mere kraftfuldt til kompleks logik.
Vigtige jq-mønstre til EC2:
.Reservations[].Instances[]— udjævn strukturen med de to arrays.select(.State.Name == "running")— filtrér efter tilstand..Tags[] | select(.Key == "Name") | .Value— udtræk en tagværdi.
Udsnittet finder en kørende instans ud fra dens Name-tag og returnerer dens ID og private IP.
#!/usr/bin/env bash
set -euo pipefail
INSTANCE_NAME="web-server-prod"
RESULT=$(aws ec2 describe-instances \
--filters \
"Name=tag:Name,Values=${INSTANCE_NAME}" \
"Name=instance-state-name,Values=running" \
--output json)
# Extract instance ID and private IP using jq
INSTANCE_ID=$(echo "$RESULT" | jq -r \
'.Reservations[].Instances[] | .InstanceId')
PRIVATE_IP=$(echo "$RESULT" | jq -r \
'.Reservations[].Instances[] | .PrivateIpAddress')
if [[ -z "$INSTANCE_ID" ]]; then
echo "[WARN] No running instance named '$INSTANCE_NAME' found."
exit 1
fi
echo "Instance ID : $INSTANCE_ID"
echo "Private IP : $PRIVATE_IP"Idempotent klargøring af IAM-rolle
IAM-ressourcer er globale og må ikke duplikeres. AWS returnerer den specifikke fejlkode EntityAlreadyExists, når du forsøger at oprette en rolle, der allerede findes. Ved større IAM-installationer er det et renere idempotensmønster at fange denne kode end først at kalde en listeforespørgsel for at kontrollere ressourcen.
Scriptet nedenfor viser:
- Hvordan CLI'ens afslutningskode opfanges med
|| true, såset -eikke afbryder scriptet. - Hvordan JSON-fejlmeddelelsen, som AWS skriver til stderr, fortolkes ved hjælp af processubstitution.
- Hvordan en politik kun tilknyttes, hvis den ikke allerede er tilknyttet.
#!/usr/bin/env bash
set -euo pipefail
ROLE_NAME="DevOpsDeployRole"
POLICY_ARN="arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess"
TRUST_POLICY='{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": { "Service": "ec2.amazonaws.com" },
"Action": "sts:AssumeRole"
}]
}'
# Attempt creation; ignore EntityAlreadyExists
CREATE_OUTPUT=$(aws iam create-role \
--role-name "$ROLE_NAME" \
--assume-role-policy-document "$TRUST_POLICY" \
--output json 2>&1) || {
if echo "$CREATE_OUTPUT" | grep -q 'EntityAlreadyExists'; then
echo "[SKIP] Role $ROLE_NAME already exists."
else
echo "[ERROR] Unexpected error: $CREATE_OUTPUT" >&2
exit 1
fi
}
# Attach policy (attach-role-policy is idempotent by default)
aws iam attach-role-policy \
--role-name "$ROLE_NAME" \
--policy-arn "$POLICY_ARN"
echo "[OK] Role $ROLE_NAME ready with policy $POLICY_ARN."jq avanceret: Omformninger, maps og toentries
Virkelige svar fra infrastruktur indeholder snesevis af felter. jq-omformninger lader dig ændre outputtet til efterfølgende værktøjer, logge eller konfigurationsfiler.
Vigtige avancerede mønstre:
map(select(...))— filtrér et array uden at miste arrayets omslutning.to_entries | map(select(.value != null))— fjern null-felter, før du skriver til en konfiguration.[.[] | {id: .InstanceId, ip: .PrivateIpAddress}]— projicér til en ny struktur.@csv,@tsv,@base64— indbyggede formatkonvertere.
Udsnittet nedenfor udtrækker alle kørende instanser og skriver en TSV-inventarfil.
#!/usr/bin/env bash
set -euo pipefail
OUTPUT_FILE="/tmp/ec2_inventory.tsv"
aws ec2 describe-instances \
--filters "Name=instance-state-name,Values=running" \
--output json \
| jq -r '
["InstanceId", "Name", "PrivateIp", "Type", "AZ"],
[
.Reservations[].Instances[] | [
.InstanceId,
(.Tags // [] | map(select(.Key == "Name")) | .[0].Value // "(none)"),
(.PrivateIpAddress // "N/A"),
.InstanceType,
.Placement.AvailabilityZone
]
][]
| @tsv' > "$OUTPUT_FILE"
echo "Inventory written to $OUTPUT_FILE:"
column -t "$OUTPUT_FILE"Ventning på asynkrone handlinger: Polling med jq
Handlinger i skyen er asynkrone. Oprettelse af en EC2-instans returnerer straks med tilstanden pending. Pålidelige scripts skal polle, indtil den ønskede tilstand er nået, før de fortsætter.
Mønsteret nedenfor bruger en until-løkke med eksponentiel backoff. AWS CLI tilbyder også wait-underkommandoer (f.eks. aws ec2 wait instance-running), men hjemmelavet polling giver dig kontrol over timeout og mere detaljeret logning.
#!/usr/bin/env bash
set -euo pipefail
INSTANCE_ID="i-0abcdef1234567890"
MAX_WAIT=300 # seconds
INTERVAL=10
ELAPSED=0
echo "Waiting for instance $INSTANCE_ID to reach 'running' state..."
while true; do
STATE=$(aws ec2 describe-instances \
--instance-ids "$INSTANCE_ID" \
--output json \
| jq -r '.Reservations[0].Instances[0].State.Name')
echo " [$(date +%T)] state = $STATE"
[[ "$STATE" == "running" ]] && break
if [[ "$STATE" == "terminated" || "$STATE" == "shutting-down" ]]; then
echo "[FATAL] Instance entered terminal state: $STATE" >&2
exit 1
fi
if (( ELAPSED >= MAX_WAIT )); then
echo "[TIMEOUT] Instance did not reach 'running' after ${MAX_WAIT}s." >&2
exit 1
fi
sleep "$INTERVAL"
(( ELAPSED += INTERVAL ))
done
echo "[OK] Instance $INSTANCE_ID is running."Mønster til flere skyer: Modstykker i GCP og Azure
Mønsteret med først at læse og derefter handle kan overføres direkte til andre CLI-værktøjer til skytjenester. Både gcloud og az returnerer JSON og understøtter filtrering:
- GCP:
gcloud ... --format='json'— send outputtet tiljqpræcis som med AWS. Bruggcloud ... --quiettil at undertrykke spørgsmål i scripts. - Azure:
az ... --output json— samme mønster.az group existsreturnerer en almindelig boolesk streng (true/false), såjqer ikke nødvendigt i simple tilfælde.
Udsnittet viser idempotent oprettelse af ressourcegrupper i Azure og GCS-buckets i GCP side om side ved hjælp af det samme betingelsesmønster.
#!/usr/bin/env bash
set -euo pipefail
# --- Azure: idempotent resource group ---
RG="devops-rg"
LOCATION="westeurope"
if [[ $(az group exists --name "$RG") == "true" ]]; then
echo "[SKIP] Azure resource group $RG already exists."
else
echo "[CREATE] Creating Azure resource group $RG..."
az group create --name "$RG" --location "$LOCATION" --output json \
| jq '{name: .name, location: .location, provisioningState: .properties.provisioningState}'
fi
# --- GCP: idempotent GCS bucket ---
GCS_BUCKET="gs://devops-artifacts-prod"
PROJECT="my-gcp-project"
if gcloud storage buckets describe "$GCS_BUCKET" \
--project="$PROJECT" --format='value(name)' &>/dev/null; then
echo "[SKIP] GCS bucket $GCS_BUCKET already exists."
else
echo "[CREATE] Creating GCS bucket $GCS_BUCKET..."
gcloud storage buckets create "$GCS_BUCKET" \
--project="$PROJECT" \
--location=EU \
--uniform-bucket-level-access
fiNedtagning: Sikker destruktion af ressourcer
Scripts til destruktion er lige så vigtige som scripts til oprettelse. En sikker nedtagning:
- Viser ressourcer før noget slettes og udskriver en oversigt til menneskelig gennemgang.
- Accepterer flaget
--dry-run, så operatører kan bekræfte planen uden at udføre handlinger. - Sletter i den korrekte afhængighedsrækkefølge (f.eks. afsluttes instanser, før sikkerhedsgrupper slettes).
Udsnittet nedenfor afslutter alle EC2-instanser med tagget Env=staging og bruger en dry-run-betingelse.
#!/usr/bin/env bash
set -euo pipefail
DRY_RUN="${1:-}"
echo "Finding staging EC2 instances..."
INSTANCE_IDS=$(aws ec2 describe-instances \
--filters \
"Name=tag:Env,Values=staging" \
"Name=instance-state-name,Values=running,stopped" \
--output json \
| jq -r '[.Reservations[].Instances[].InstanceId] | @sh')
if [[ -z "$INSTANCE_IDS" ]]; then
echo "[INFO] No staging instances found. Nothing to do."
exit 0
fi
echo "Instances to terminate: $INSTANCE_IDS"
if [[ "$DRY_RUN" == "--dry-run" ]]; then
echo "[DRY-RUN] No changes made."
exit 0
fi
read -rp "Terminate these instances? [yes/N]: " CONFIRM
[[ "$CONFIRM" != "yes" ]] && { echo "Aborted."; exit 0; }
# shellcheck disable=SC2086
aws ec2 terminate-instances --instance-ids $INSTANCE_IDS --output json \
| jq '.TerminatingInstances[] | {id: .InstanceId, state: .CurrentState.Name}'
echo "[DONE] Termination initiated."Fra ende til anden: Idempotent initialiseringsscript til infrastruktur
Det hele samlet: Et initialiseringsscript i produktionskvalitet orkestrerer flere ressourcer i den rigtige rækkefølge, er fuldt idempotent og udsender strukturerede logge, som et CI-system kan fortolke.
Vigtige fremgangsmåder:
- Struktureret logning via en
log()-hjælpefunktion, der sætter[INFO],[WARN]eller[ERROR]foran meddelelserne. - Tilstandsfil — skriv id'er for oprettede ressourcer til en JSON-tilstandsfil, så efterfølgende kørsler og nedtagningsscripts deler de samme referencer.
- Fejlhåndtering —
trapfanger uventede afslutninger og rapporterer nummeret på den fejlede linje.
#!/usr/bin/env bash
set -euo pipefail
STATE_FILE="/tmp/infra_state.json"
REGION="eu-west-1"
BUCKET="devops-bootstrap-$(date +%Y%m)"
ROLE="BootstrapRole"
log() { echo "[$(date -u +%T)] [$1] ${*:2}"; }
trap 'log ERROR "Script failed at line $LINENO"' ERR
# Initialize state
[[ -f "$STATE_FILE" ]] || echo '{}' > "$STATE_FILE"
# --- Step 1: S3 bucket ---
EXISTING_BUCKETS=$(aws s3api list-buckets --query 'Buckets[].Name' --output json)
if echo "$EXISTING_BUCKETS" | jq -e --arg b "$BUCKET" 'index($b) != null' > /dev/null; then
log INFO "Bucket $BUCKET exists — skipping."
else
aws s3api create-bucket --bucket "$BUCKET" --region "$REGION" \
--create-bucket-configuration LocationConstraint="$REGION" > /dev/null
log INFO "Bucket $BUCKET created."
fi
# Update state file
jq --arg b "$BUCKET" '.bucket = $b' "$STATE_FILE" > /tmp/_state_tmp && mv /tmp/_state_tmp "$STATE_FILE"
# --- Step 2: IAM role ---
if aws iam get-role --role-name "$ROLE" &>/dev/null; then
log INFO "Role $ROLE exists — skipping."
else
aws iam create-role --role-name "$ROLE" \
--assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"ec2.amazonaws.com"},"Action":"sts:AssumeRole"}]}' \
--output json | jq '{RoleName: .Role.RoleName, Arn: .Role.Arn}'
log INFO "Role $ROLE created."
fi
jq --arg r "$ROLE" '.role = $r' "$STATE_FILE" > /tmp/_state_tmp && mv /tmp/_state_tmp "$STATE_FILE"
log INFO "Bootstrap complete. State: $(cat "$STATE_FILE" | jq -c .)"Videnstjek: jq's idempotenssikring
Tjek din forståelse af idempotent cloudautomatisering med jq.
Opsummering: Cloudressourcer via CLI og jq
Denne lektion gennemgik hele livscyklussen for idempotent cloudautomatisering ved hjælp af shellscripts, cloud-CLI'er og jq.
Grundprincipper:
- Læs før skriv — forespørg altid den eksisterende tilstand først; handl kun på forskellen.
- jq -e til kontrolbetingelser — brug tilstanden for afslutningsstatus til at styre
if-grene ud fra JSON-svar. - Semantik for fejlkoder — indfang udbyderspecifikke fejlkoder (f.eks.
EntityAlreadyExists) i stedet for at lave en forhåndsoplistning, når det er mere effektivt. - Afvent asynkron tilstand — brug
until-løkker med tidsgrænser; antag aldrig, at en ressource er klar umiddelbart efter oprettelsen. - Tilstandsfiler — skriv ressource-id'er til en delt JSON-fil, så hver fase af scriptet og nedtagningen deler de samme referencer.
- Flag til prøvekørsel — understøt altid
--dry-run, så operatøren sikkert kan gennemgå ændringerne før destruktive handlinger.
Disse mønstre — kombineret med en streng set -euo pipefail-indledning og en ERR-fejlhåndtering — udgør grundlaget for infrastrukturscripting i produktionskvalitet på C2-niveau.
Lær Bash med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 22
- Lektioner
- 88
Ofte stillede spørgsmål
Er lektionen “Scripting af cloudressourcer via CLI og jq” gratis?
Ja — hele teksten til “Scripting af cloudressourcer via CLI og jq” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Linux-kommandolinjen og Bash-scripting på ekspertniveau-kurset, skal du opgradere til CoddyKit PRO. Linux-kommandolinjen og Bash-scripting på ekspertniveau-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Scripting af cloudressourcer via CLI og jq”?
Styr cloududbyderes CLI'er idempotent, og fortolk JSON-svar for at oprette og nedlægge ressourcer. Du øver dig i Linux-kommandolinjen og Bash-scripting på ekspertniveau med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Linux-kommandolinjen og Bash-scripting på ekspertniveau?
Der kræves ingen tidligere erfaring. Linux-kommandolinjen og Bash-scripting på ekspertniveau på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 3 af 4.
Hvor lang tid tager lektionen “Scripting af cloudressourcer via CLI og jq”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Linux-kommandolinjen og Bash-scripting på ekspertniveau-lektion?
Ja. Alle Linux-kommandolinjen og Bash-scripting på ekspertniveau-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Skriv slanke Dockerfiles og shell-entrypoints
- Skabelondannelse af konfigurationer med envsubst og heredocs
- Scripting af cloudressourcer via CLI og jq
- Health probes, readiness gates og venteløkker