Azure-CLI-Dateitransfers automatisieren und Bytes prüfen
Senden Sie mit az storage blob upload eine lokale Datei an Azure Blob Storage, laden Sie sie
anschließend herunter und vergleichen Sie die Bytes. Das folgende Skript erledigt dies für eine
Datei oder ein Verzeichnis mit Dateien. Es lehnt bestehende Blobnamen ab und meldet einen Stapel
nur dann als abgeschlossen, wenn jede ausgewählte Datei den Vergleich besteht.
Installation und Einrichtung
Diese Anleitung verwendet Bash unter Linux und den Azure-CLI-Container von Microsoft, getestet mit Azure CLI 2.91.0. Sie benötigen eine funktionierende Docker-Installation, die Berechtigung zum Ausführen von Containern und ein beschreibbares Arbeitsverzeichnis. Lassen Sie die Quelldateien während der Übertragung unverändert. Für Übertragungen und Speicherung fallen Azure-Gebühren an; beginnen Sie mit kleinen Dateien ohne sensible Inhalte.
Der Container enthält Bash und Python. Das Skript benötigt daher keine Azure-CLI-Installation auf dem Host. Details zur Installation des Images finden Sie in Microsofts Container-Anleitung. Laden Sie das getestete Image herunter und prüfen Sie die darin enthaltene CLI:
docker pull mcr.microsoft.com/azure-cli:2.91.0-azurelinux3.0 &&
docker run --rm mcr.microsoft.com/azure-cli:2.91.0-azurelinux3.0 az version
Ziel und Autorisierung wählen
Verwenden Sie ein bestehendes Speicherkonto und einen privaten Blob-Container, für die Ihre Administration Ihnen Schreibzugriff erteilt hat. Verwenden Sie für neue Konten den Typ „Universell v2“, wie in Microsofts Kontoübersicht beschrieben. Privat bedeutet hier, dass der anonyme Blobzugriff deaktiviert ist. Ihr Rechner benötigt weiterhin eine funktionierende Netzwerkverbindung zum Blob-Endpunkt des Kontos.
Dieses Beispiel verwendet die Authentifizierung mit Shared Key. Ihre Administration muss diese
explizit erlauben und den Kontonamen sowie den Schlüssel über Ihren Secret-Manager als exportierte
Umgebungsvariablen AZURE_STORAGE_ACCOUNT und AZURE_STORAGE_KEY bereitstellen.
Der Schlüssel gewährt weitreichenden Kontozugriff: Halten Sie ihn aus Skripten, dem Shell-Verlauf
und Protokollen heraus. Führen Sie dies nur dort aus, wo diese Autorisierung angemessen ist.
Microsoft empfiehlt die Autorisierung mit Microsoft Entra,
sofern verfügbar. Bei --auth-mode login benötigt die Identität eine Rolle für
Blobdaten; eine Rolle zur Speicherverwaltung allein reicht nicht aus. Dieses Skript verlangt
bewusst einen bereitgestellten Schlüssel. Es meldet sich nicht an, ruft keine Kontoschlüssel ab,
erstellt keine Ressourcen und weist keine Rollen zu. Ein Konto, das Shared Key deaktiviert,
benötigt eine andere Authentifizierungseinrichtung.
Dateien mit Azure CLI übertragen
Speichern Sie Folgendes als transfer.sh in Ihrem Arbeitsverzeichnis. Die vier
Argumente sind die Quelldatei oder das Quellverzeichnis, der Name des bestehenden Containers, das
neue Präfix für Blobnamen und das neue Downloadverzeichnis. Verwenden Sie relative Pfade innerhalb
dieses Arbeitsverzeichnisses, etwa ./input.bin und
./downloads, damit der Container darauf zugreifen kann. Das übergeordnete
Verzeichnis des Downloadverzeichnisses muss bereits existieren.
Quellpfade und Dateinamen müssen gültiges UTF-8 sein und dürfen keine Wagenrückläufe oder
Zeilenumbrüche enthalten. Leerzeichen, wörtliche Prozentzeichen, #,
?, führende Bindestriche und Unicode-Dateinamen werden unterstützt.
Das Präfix verwendet ASCII-Kleinbuchstaben, Ziffern, Schrägstriche, Unterstriche und Bindestriche.
Beginnen Sie es mit einem Buchstaben oder einer Ziffer und vermeiden Sie leere Segmente,
. oder ... Ein Präfix wie
transfers/run-001 erstellt verschachtelte Blobnamen, ohne dass Sie entfernte
Verzeichnisse erstellen müssen.
#!/usr/bin/env bash
set -uo pipefail
for tool in az python3 mkdir sleep; do
command -v "$tool" >/dev/null || { printf 'Missing tool: %s\n' "$tool" >&2; exit 1; }
done
: "${AZURE_STORAGE_ACCOUNT:?Set AZURE_STORAGE_ACCOUNT}"
: "${AZURE_STORAGE_KEY:?Set AZURE_STORAGE_KEY}"
unset AZURE_STORAGE_CONNECTION_STRING AZURE_STORAGE_SAS_TOKEN AZURE_STORAGE_SERVICE_ENDPOINT
if [ "$#" -ne 4 ]; then
printf 'Usage: bash transfer.sh SOURCE CONTAINER PREFIX DOWNLOAD_DIR\n' >&2
exit 2
fi
source_path=$1
container=$2
prefix=$3
download_dir=$4
case "$source_path" in /*) ;; *) source_path="./$source_path" ;; esac
case "$download_dir" in /*) ;; *) download_dir="./$download_dir" ;; esac
if ! python3 - "$source_path" "$prefix" "$download_dir" <<'PY'
import os
import re
import sys
try:
source, prefix, destination = sys.argv[1:]
paths = [source, destination]
if os.path.isdir(source):
with os.scandir(source) as entries:
paths.extend(entry.path for entry in entries
if entry.is_file(follow_symlinks=False))
for path in paths:
os.fsencode(path).decode('utf-8')
if '\n' in path or '\r' in path:
raise ValueError()
if not re.fullmatch(r'[a-z0-9][a-z0-9/_-]*', prefix):
raise ValueError()
if any(part in ('', '.', '..') for part in prefix.split('/')):
raise ValueError()
except (OSError, UnicodeError, ValueError):
print('Check source access, UTF-8 paths, and the blob prefix.', file=sys.stderr)
sys.exit(1)
PY
then
exit 1
fi
if [ -L "$source_path" ] || { [ ! -f "$source_path" ] && [ ! -d "$source_path" ]; }; then
printf 'Source must be a regular file or directory, not a symbolic link.\n' >&2
exit 1
fi
mkdir -- "$download_dir" || exit 1
shopt -s nullglob dotglob
files=("$source_path")
if [ -d "$source_path" ]; then files=("$source_path"/*); fi
failed=0
verified=0
max_retries=3
for file in "${files[@]}"; do
[ -f "$file" ] && [ ! -L "$file" ] || continue
filename=${file##*/}
blob_name="$prefix/$filename"
uploaded=0
for ((attempt=1; attempt<=max_retries; attempt++)); do
if az storage blob upload --account-name "$AZURE_STORAGE_ACCOUNT" \
--container-name "$container" --name "$blob_name" --file "$file" \
--type block --auth-mode key --overwrite false \
--only-show-errors --output none >/dev/null 2>&1; then
uploaded=1
break
fi
if [ "$attempt" -lt "$max_retries" ]; then sleep 5; fi
done
if [ "$uploaded" -eq 0 ]; then
printf 'Upload refused or failed: %s\n' "$filename" >&2
failed=$((failed + 1))
continue
fi
downloaded_file="$download_dir/$filename"
if ! az storage blob download --account-name "$AZURE_STORAGE_ACCOUNT" \
--container-name "$container" --name "$blob_name" --file "$downloaded_file" \
--auth-mode key --overwrite false --only-show-errors --output none >/dev/null 2>&1; then
printf 'Download failed: %s\n' "$filename" >&2
failed=$((failed + 1))
continue
fi
if ! python3 - "$file" "$downloaded_file" <<'PY'
import filecmp
import sys
sys.exit(0 if filecmp.cmp(sys.argv[1], sys.argv[2], shallow=False) else 1)
PY
then
printf 'Byte comparison failed: %s\n' "$filename" >&2
failed=$((failed + 1))
continue
fi
printf 'Verified: %s\n' "$filename"
verified=$((verified + 1))
done
printf 'Verified %s file(s); failed %s.\n' "$verified" "$failed"
if [ "$failed" -ne 0 ]; then exit 1; fi
printf 'Transfer complete\n'
Dateien hochladen
Legen Sie eine Datei namens input.bin neben dem gespeicherten Skript ab.
Wenn die beiden Zugangsdatenvariablen bereits exportiert sind, ersetzen Sie
your-container durch Ihren bestehenden Container und wählen Sie ein neues Präfix.
Führen Sie Folgendes aus:
docker run --rm --user "$(id -u):$(id -g)" \
--env HOME=/tmp --env AZURE_CONFIG_DIR=/tmp/azure \
--env AZURE_CORE_COLLECT_TELEMETRY=no \
--env AZURE_STORAGE_ACCOUNT --env AZURE_STORAGE_KEY \
--mount "type=bind,source=$PWD,target=/work" --workdir /work \
mcr.microsoft.com/azure-cli:2.91.0-azurelinux3.0 \
bash transfer.sh ./input.bin your-container transfers/run-001 ./downloads
Der Container wird danach beendet; der hochgeladene Blob bleibt in Azure und der Download in Ihrem
Arbeitsverzeichnis. Die Option --user sorgt dafür, dass die
heruntergeladenen Dateien Ihrem Linux-Benutzer gehören.
Dateien herunterladen
Der Befehl az storage blob download im Skript ruft genau den Blobnamen ab, den das Skript
hochgeladen hat. Python vergleicht den vollständigen Download mit der lokalen Quelle. Ein
erfolgreicher Durchlauf mit einer einzelnen Datei gibt Verified: input.bin aus, dann
Verified 1 file(s); failed 0. und Transfer complete. Leere Dateien sind ebenfalls
gültig. Wenn nach einem erfolgreichen Upload der Download oder Vergleich fehlschlägt, wird ein
Status ungleich null zurückgegeben. Der entfernte Blob bleibt zur Untersuchung erhalten.
Beide Übertragungen verwenden explizit --overwrite false; siehe die
Upload-Referenz
und die Download-Referenz.
Das Skript lehnt außerdem ein bestehendes Downloadverzeichnis ab, bevor es Azure kontaktiert.
Wählen Sie für einen erneuten Durchlauf ein neues Präfix und ein neues Downloadverzeichnis.
Die Wiederverwendung eines Blobnamens mit einem neuen Downloadverzeichnis schlägt fehl, statt den
vorherigen Blob zu ersetzen. Diese Ablehnung ist beabsichtigt; das Skript implementiert weder das
Ersetzen am selben Speicherort noch ein Rollback.
Stapelübertragungen von Dateien mit Azure CLI automatisieren
Legen Sie Ihre Dateien in ./input ab und verwenden Sie dann dasselbe Skript
mit diesem Verzeichnis als erstem Argument:
docker run --rm --user "$(id -u):$(id -g)" \
--env HOME=/tmp --env AZURE_CONFIG_DIR=/tmp/azure \
--env AZURE_CORE_COLLECT_TELEMETRY=no \
--env AZURE_STORAGE_ACCOUNT --env AZURE_STORAGE_KEY \
--mount "type=bind,source=$PWD,target=/work" --workdir /work \
mcr.microsoft.com/azure-cli:2.91.0-azurelinux3.0 \
bash transfer.sh ./input your-container transfers/batch-001 ./batch-downloads
Damit werden reguläre Dateien direkt in ./input ausgewählt, einschließlich
versteckter Dateien. Unterverzeichnisse und symbolische Links werden übersprungen; die Auswahl ist
nicht rekursiv. Jeder ausgewählte Dateiname wird zum letzten Segment seines Blobnamens und seines
lokalen Downloadnamens. Ein leeres Verzeichnis wird mit null verifizierten Dateien abgeschlossen.
Prüfen Sie daher die ausgegebene Anzahl, wenn Sie einen größeren Bestand erwartet haben.
Die Übertragungen laufen nacheinander. Für jeden Upload wird die CLI höchstens dreimal aufgerufen,
nach einem Fehlschlag jeweils mit fünf Sekunden Abstand. Die eigenen Wiederholungsversuche der
CLI für den Dienst kommen hinzu. Für Downloads wird die CLI einmal aufgerufen. Die abschließende
Zählung umfasst alle fehlgeschlagenen Uploads, Downloads und Vergleiche, auch wenn spätere Dateien
erfolgreich sind. Ein teilweise erfolgreicher Stapel endet mit einem Status ungleich null und
behält seine erfolgreichen Blobs und Downloads bei. Für dieses Ergebnis wird niemals
Transfer complete ausgegeben.
Häufige Probleme beheben
Fehlt eine Zugangsdatenvariable, stoppt das Skript, bevor es das Downloadverzeichnis erstellt. Prüfen Sie bei einem abgelehnten Upload gemeinsam mit der Administration das ausgewählte Konto, den Container, die Schlüsselautorisierung und die Netzwerkverbindung. Das Skript meldet den betroffenen Dateinamen und unterdrückt unverarbeitete CLI-Diagnosen, damit Zugangsdaten und signierte URLs nicht in seiner Ausgabe erscheinen.
Ein fehlgeschlagener Upload kann auch bedeuten, dass der Blobname bereits existiert. Drei abgelehnte Versuche machen das Ersetzen nicht sicher. Eine verlorene Antwort kann dazu führen, dass ein Blob bereits verbindlich gespeichert ist, obwohl der Befehl fehlgeschlagen ist. Prüfen Sie genau diesen Namen vor einem erneuten Versuch. Verwenden Sie für eine weitere Kopie ein neues Präfix, statt die Überschreibrichtlinie zu ändern, um eine Ablehnung zu umgehen.
Wenn der Download oder Vergleich fehlschlägt, untersuchen Sie den aufbewahrten Blob und den lokalen Download getrennt. Lassen Sie die ursprüngliche Quelle unverändert. Das Skript löscht keine unvollständigen Downloads, macht erfolgreiche Uploads nicht rückgängig und ändert keine Aufbewahrungseinstellungen des Kontos. Stimmen Sie eine Bereinigung mit der für die Ressource verantwortlichen Person ab und verwenden Sie dabei die exakten Blobnamen dieses Durchlaufs.
Nächste Schritte
Informationen zu direkten HTTP-Anfragen statt CLI-Automatisierung finden Sie unter Dateien mit cURL nach Azure exportieren. Dies ist ein separater REST-Ablauf; dessen Authentifizierung und Uploadprogramm werden hier nicht benötigt.
