Skripting av skyressurser med CLI og jq
Styr CLI-er for skyleverandører idempotent, og analyser JSON-svar for å opprette og fjerne ressurser.
Skripting av skyressurser med CLI og jq er en gratis leksjon i Mestring av Linux-kommandolinjen og Bash-skripting på CoddyKit. Dette er leksjon 3 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Mestring av Linux-kommandolinjen og Bash-skripting, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Mestring av Linux-kommandolinjen og Bash-skripting inneholder totalt 4 leksjoner.
Hvorfor idempotent skripting i skyen er viktig
På C2-nivå handler skripting i skyen ikke om å klikke på knapper — det handler om å skrive kode som kan kjøres trygt flere ganger uten å opprette dupliserte ressurser eller mislykkes ved andre kjøring.
Et idempotent skript kontrollerer om en ressurs allerede finnes, før den opprettes. Dette er grunnlaget for pålitelig infrastrukturautomatisering.
- Cloud CLI-er (AWS, GCP, Azure) returnerer JSON — det er avgjørende å analysere disse utdataene.
jqer standardverktøyet i Unix for å hente ut, filtrere og transformere JSON fra skallskript.- Ved å kombinere CLI, jq og betinget logikk kan De skrive robuste og repeterbare klargjøringsskript.
Gjennom denne leksjonen skal De klargjøre S3-buckets, EC2-instanser og IAM-roller ved hjelp av AWS CLI som referanse, med mønstre som kan overføres direkte til gcloud og az.
Installere og kontrollere cloud-CLI-er
Før skripting må De kontrollere at de riktige verktøyene er tilgjengelige. Bruk alltid fastlåste versjoner i CI for å unngå avvik mellom miljøer.
Kodeutdraget nedenfor kontrollerer AWS CLI v2, jq og GCP SDK, og installerer bare det som mangler — et mønster som er nyttig i bootstrap-skript for 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."Spørre etter eksisterende ressurser med jq
Det første steget i ethvert idempotent skript er en lesing — spør API-et om ressursen allerede finnes, og velg deretter riktig gren.
AWS CLI returnerer alltid JSON. jq lar Dem hente ut nøyaktig feltet De trenger:
jq -r '.Buckets[].Name'— rå strengutdata, ett bucket-navn per linje.jq -e— avslutter med kode 1 hvis uttrykket girnullellerfalse, noe som gjør det ideelt forif-betingelser.jq '.[] | select(.Name == env.BUCKET)'— filtrer ved hjelp av en skallvariabel gjennomenv.
Kodeutdraget nedenfor viser alle S3-buckets og kontrollerer om en mål-bucket allerede finnes.
#!/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 opprettelse av S3-bucket
Når kontrollen av om ressursen finnes, er på plass, pakker De opprettelsen inn i en betingelse. En godt strukturert cloud-funksjon følger dette mønsteret:
- Les gjeldende tilstand fra API-et.
- Sammenlign ønsket tilstand med faktisk tilstand.
- Utfør bare endringer som følger av avviket.
Legg merke til flagget --create-bucket-configuration — det er nødvendig i alle regioner unntatt us-east-1. Ved å hardkode regionen i skriptet unngås stille feil når AWS_DEFAULT_REGION ikke er satt.
#!/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"Analysere nestet JSON: EC2-instansens tilstand
EC2-svar er dypt nestet. Både sti-traversering med jq og --query (JMESPath, innebygd i AWS CLI) fungerer — men jq er kraftigere for kompleks logikk.
Viktige jq-mønstre for EC2:
.Reservations[].Instances[]— flat ut den doble array-strukturen.select(.State.Name == "running")— filtrer etter tilstand..Tags[] | select(.Key == "Name") | .Value— hent ut en tag-verdi.
Kodeutdraget finner en kjørende instans ut fra Name-taggen og returnerer ID-en og den private IP-adressen.
#!/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 klargjøring av IAM-roller
IAM-ressurser er globale og må ikke dupliseres. AWS returnerer en bestemt feilkode — EntityAlreadyExists — når De prøver å opprette en rolle som allerede finnes. Å håndtere denne koden er et ryddigere idempotensmønster enn et forhåndskall for å liste ressurser når IAM brukes i stor skala.
Skriptet nedenfor viser:
- Hvordan CLI-ens avslutningskode fanges opp med
|| true, slik atset -eikke avbryter skriptet. - Hvordan feilmeldingen i JSON som AWS skriver til stderr, analyseres ved hjelp av prosessubstitusjon.
- Hvordan en policy bare knyttes til rollen hvis den ikke allerede er knyttet til den.
#!/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."Avansert jq: Transformasjoner, map og toentries
Reelle infrastruktursvar inneholder dusinvis av felt. Transformasjoner med jq lar Dem omforme utdata for etterfølgende verktøy, logger eller konfigurasjonsfiler.
Viktige avanserte mønstre:
map(select(...))— filtrer en array uten å miste array-innpakningen.to_entries | map(select(.value != null))— fjern null-felt før skriving til en konfigurasjon.[.[] | {id: .InstanceId, ip: .PrivateIpAddress}]— projiser til en ny struktur.@csv,@tsv,@base64— innebygde formatkonverterere.
Kodeutdraget nedenfor henter ut alle kjø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"Vente på asynkrone operasjoner: Polling med jq
Skyoperasjoner er asynkrone. Når en EC2-instans opprettes, returneres resultatet umiddelbart med tilstanden pending. Pålitelige skript må polle til ønsket tilstand er nådd før de fortsetter.
Mønsteret nedenfor bruker en until-løkke med eksponentiell backoff. AWS CLI tilbyr også wait-underkommandoer (for eksempel aws ec2 wait instance-running), men egen polling gir Dem kontroll over tidsavbrudd og mer detaljert logging.
#!/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."Multi-cloud-mønster: Tilsvarende løsninger for GCP og Azure
Les-og-handle-mønsteret for idempotens kan overføres direkte til andre cloud-CLI-er. Både gcloud og az returnerer JSON og støtter filtrering:
- GCP:
gcloud ... --format='json'— send utdataene tiljqpå nøyaktig samme måte som med AWS. Brukgcloud ... --quietfor å undertrykke spørsmål i skript. - Azure:
az ... --output json— samme mønster.az group existsreturnerer en ren boolsk streng (true/false), slik at jq ikke trengs i enkle tilfeller.
Kodeutdraget viser idempotent opprettelse av ressursgrupper i Azure og GCS-buckets i GCP side om side, ved hjelp av det samme betingelsesmønsteret.
#!/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
fiNedmontering: Sikker destruksjon av ressurser
Skript for destruksjon er like viktige som skript for opprettelse. En sikker nedmontering:
- Viser ressurser før noe slettes og skriver ut et sammendrag for menneskelig gjennomgang.
- Godtar flagget
--dry-run, slik at operatører kan bekrefte planen uten å utføre den. - Sletter i riktig avhengighetsrekkefølge (for eksempel avslutte instanser før sikkerhetsgrupper slettes).
Kodeutdraget nedenfor avslutter alle EC2-instanser med taggen Env=staging med 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."Ende-til-ende: Idempotent oppstartsskript for infrastruktur
Når alt settes sammen: Et oppstartsskript for infrastruktur på produksjonsnivå orkestrerer flere ressurser i riktig rekkefølge, er fullstendig idempotent og genererer strukturerte logger som et CI-system kan analysere.
Viktige fremgangsmåter som demonstreres:
- Strukturert logging via en
log()-hjelpefunksjon som setter[INFO],[WARN]eller[ERROR]foran hver melding. - Tilstandsfil — skriv ID-ene til opprettede ressurser til en JSON-tilstandsfil, slik at etterfølgende kjøringer og nedmonteringsskript kan dele de samme referansene.
- Feilfanging —
trapfanger opp uventede avslutninger og rapporterer linjenummeret der feilen oppsto.
#!/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 .)"Kunnskapssjekk: jq-vakt for idempotens
Test forståelsen Deres av idempotent skripting i skyen med jq.
Oppsummering: Skripting av skyressurser med CLI og jq
Denne leksjonen dekket hele livssyklusen for idempotent skyautomatisering ved hjelp av shell-skript, sky-CLI-er og jq.
Grunnprinsipper:
- Les før skriving — spør alltid etter eksisterende tilstand først, og utfør bare handlinger for differansen.
- jq -e for vakter — bruk modus for avslutningsstatus til å styre
if-grener basert på JSON-svar. - Semantikk for feilkoder — fang leverandørspesifikke feilkoder, for eksempel
EntityAlreadyExists, i stedet for å liste opp ressurser på forhånd når det er mer effektivt. - Avvent asynkron tilstand — bruk
until-løkker med tidsavbrudd, og anta aldri at en ressurs er klar umiddelbart etter opprettelse. - Tilstandsfiler — skriv ressurs-ID-er til en delt JSON-fil, slik at hver fase av skriptet og nedmonteringen deler de samme referansene.
- Flagg for prøvekjøring — støtt alltid
--dry-run, slik at operatøren trygt kan gjennomgå handlingene før destruktive operasjoner utføres.
Disse mønstrene — kombinert med en streng set -euo pipefail-header og en ERR-felle — danner grunnlaget for skripting av infrastruktur på produksjonsnivå på C2-nivå.
Lær deg Bash med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 22
- Leksjoner
- 88
Ofte stilte spørsmål
Er leksjonen «Skripting av skyressurser med CLI og jq» gratis?
Ja – hele teksten i «Skripting av skyressurser med CLI og jq» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av Mestring av Linux-kommandolinjen og Bash-skripting-kurset, kan du oppgradere til CoddyKit PRO. Kurset i Mestring av Linux-kommandolinjen og Bash-skripting inneholder totalt 4 leksjoner.
Hva lærer jeg i «Skripting av skyressurser med CLI og jq»?
Styr CLI-er for skyleverandører idempotent, og analyser JSON-svar for å opprette og fjerne ressurser. Du øver på Mestring av Linux-kommandolinjen og Bash-skripting med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med Mestring av Linux-kommandolinjen og Bash-skripting?
Ingen tidligere erfaring er nødvendig. Mestring av Linux-kommandolinjen og Bash-skripting på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 3 av 4.
Hvor lang tid tar leksjonen «Skripting av skyressurser med CLI og jq»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne Mestring av Linux-kommandolinjen og Bash-skripting-leksjonen?
Ja. Alle Mestring av Linux-kommandolinjen og Bash-skripting-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.
Alle leksjonene i dette kurset
- Slanke Dockerfiles og shell-entrypoint-er
- Maler for konfigurasjoner med envsubst og heredoc-er
- Skripting av skyressurser med CLI og jq
- Helsetester, readiness-sperrer og venteløkker