CustomScript-Erweiterung für Windows

Die benutzerdefinierte Skripterweiterung lädt Skripts auf virtuelle Azure-Computer (VMs) herunter und führt sie aus. Diese Erweiterung ist hilfreich bei der Konfiguration nach der Bereitstellung, bei der Softwareinstallation oder bei anderen Konfigurations- oder Verwaltungsaufgaben. Sie können Skripts von Azure Storage oder GitHub herunterladen oder zur Laufzeit der Erweiterung für das Azure-Portal bereitstellen.

Die Erweiterung für benutzerdefinierte Skripts ist mit Azure Resource Manager-Vorlagen integriert. Sie können sie auch mithilfe der Azure CLI, des Azure-Portals, der Azure Virtual Machines-REST-API oder mithilfe von PowerShell ausführen.

In diesem Artikel erfahren Sie, wie Sie die benutzerdefinierte Skripterweiterung mithilfe des Azure PowerShell-Moduls und Azure Resource Manager-Vorlagen verwenden. Außerdem werden Schritte zur Problembehandlung für Windows Systeme beschrieben.

Voraussetzungen

Hinweis

Verwenden Sie die benutzerdefinierte Skripterweiterung nicht, um Update-AzVM mit der gleichen VM als Parameter auszuführen, da der Befehl dann auf sich selbst wartet.

Betriebssystem

Die benutzerdefinierte Skripterweiterung für Windows wird unter den folgenden unterstützten Betriebssystemen ausgeführt:

  • Windows Server 2008 R2
  • Windows Server 2012
  • Windows Server 2012 R2
  • Windows 10
  • Windows Server 2016
  • Windows Server 2016 Core
  • Windows Server 2019
  • Windows Server 2019 Core
  • Windows Server 2022
  • Windows Server 2022 Core
  • Windows 11

Speicherort des Skripts

Sie können die Erweiterung so konfigurieren, dass mit Ihren Azure Blob Storage-Anmeldeinformationen auf Azure Blob Storage zugegriffen wird. Das Skript kann an einem beliebigen Ort gespeichert werden, solange der virtuelle Computer eine Route zu diesem Endpunkt (z. B. GitHub oder interner Dateiserver) einrichten kann.

Internetkonnektivität

Wenn Sie ein Skript extern herunterladen möchten, etwa von GitHub oder Azure Storage, müssen zusätzliche Firewall- oder Netzwerksicherheitsgruppen-Ports (NSG) geöffnet werden. Wenn sich Ihr Skript beispielsweise in Azure Storage befindet, können Sie Zugriff über Azure-NSG-Diensttags für Storage gewähren.

Bitte beachten Sie, dass die benutzerdefinierte Skripterweiterung keine Möglichkeit zum Umgehen der Zertifikatüberprüfung bietet. Wenn Sie den Download von einem geschützten Speicherort durchführen, z. B. mit einem selbstsigniert Zertifikat, erhalten Sie möglicherweise einen Fehler wie etwa „Das Remotezertifikat ist laut Validierungsverfahren ungültig“. Stellen Sie sicher, dass das Zertifikat ordnungsgemäß im Speicher Vertrauenswürdige Stammzertifizierungsstellen auf dem virtuellen Computer installiert ist.

Wenn sich Ihr Skript auf einem lokalen Server befindet, müssen Sie möglicherweise weitere Firewall- oder NSG-Ports öffnen.

Tipps und Tricks

  • Der Grund für die höchste Fehlerrate für diese Erweiterung sind Syntaxfehler im Skript. Testen Sie, ob das Skript fehlerfrei ausgeführt wird. Fügen Sie eine zusätzliche Protokollierung in das Skript ein, um das Auffinden von Fehlern zu vereinfachen.
  • Schreiben Sie idempotente Skripts, sodass eine versehentliche mehrfache Ausführung keine Systemänderungen verursacht.
  • Stellen Sie sicher, dass während der Skriptausführung keine Benutzereingaben erforderlich sind.
  • Die Ausführung des Skripts kann 90 Minuten dauern. Alles, was länger dauert, führt zu einer fehlerhaften Bereitstellung der Erweiterung.
  • Fügen Sie keine Neustartvorgänge in das Skript ein. Diese Aktion verursacht Probleme mit anderen Erweiterungen, die installiert werden, und die Erweiterung wird nach dem Neustart nicht fortgesetzt.
  • Wenn Sie ein Skript haben, das zu einem Neustart führt, bevor Anwendungen installiert und Skripts ausgeführt werden, planen Sie den Neustart mit einer geplanten Windows-Aufgabe oder mit Tools wie DSC, Chef oder Puppet-Erweiterungen.
  • Führen Sie kein Skript aus, das bewirkt, dass der VM-Agent angehalten oder aktualisiert wird. Das kann dazu führen, dass die Erweiterung in einem Übergangszustand verbleibt und ein Timeout verursacht wird.
  • Ein Skript wird von der Erweiterung nur einmal ausgeführt. Falls Sie bei jedem Startup ein Skript ausführen möchten, sollten Sie die Erweiterung nutzen, um eine geplante Windows-Aufgabe zu erstellen.
  • Wenn Sie den Ausführungszeitpunkt eines Skripts planen möchten, verwenden Sie die Erweiterung, um einen geplanten Windows-Task zu erstellen.
  • Während der Skriptausführung wird im Azure-Portal oder in der CLI nur der Status „Im Übergang“ für die Erweiterung angezeigt. Sollten Sie häufigere Statusaktualisierungen für ein ausgeführtes Skript benötigen, müssen Sie eine eigene Lösung erstellen.
  • Die benutzerdefinierte Skripterweiterung verfügt über keine native Unterstützung von Proxyservern. Sie können aber ein Dateiübertragungstool verwenden, das Proxyserver in Ihrem Skript unterstützt, z. B. Invoke-WebRequest.
  • Achten Sie auf nicht standardmäßige Verzeichnispfade, von denen Ihre Skripts oder Befehle gegebenenfalls abhängen. Verwenden Sie eine entsprechende Logik für diese Situation.
  • Die benutzerdefinierte Skripterweiterung wird unter dem Konto „LocalSystem“ ausgeführt.
  • Wenn Sie die Eigenschaften storageAccountName und storageAccountKey verwenden möchten, müssen diese Eigenschaften in protectedSettings zugeordnet werden.

Erweiterungsschema

In der Konfiguration der benutzerdefinierten Skripterweiterung werden Aspekte wie der Skriptspeicherort und der auszuführende Befehl angegeben. Sie können diese Konfiguration in Konfigurationsdateien speichern oder sie in der Befehlszeile oder in einer Azure Resource Manager-Vorlage angeben.

Sie können sensible Daten in einer geschützten Konfiguration speichern. Diese ist verschlüsselt und wird nur auf dem virtuellen Computer entschlüsselt. Die geschützte Konfiguration ist nützlich, wenn der Ausführungsbefehl Geheimnisse wie ein Kennwort oder einen Shared Access Signature-Dateiverweis (SAS) enthält. Hier sehen Sie ein Beispiel:

{
    "apiVersion": "2018-06-01",
    "type": "Microsoft.Compute/virtualMachines/extensions",
    "name": "virtualMachineName/config-app",
    "location": "[resourceGroup().location]",
    "dependsOn": [
        "[concat('Microsoft.Compute/virtualMachines/', variables('vmName'),copyindex())]",
        "[variables('musicstoresqlName')]"
    ],
    "tags": {
        "displayName": "config-app"
    },
    "properties": {
        "publisher": "Microsoft.Compute",
        "type": "CustomScriptExtension",
        "typeHandlerVersion": "1.10",
        "autoUpgradeMinorVersion": true,
        "settings": {
            "timestamp":123456789
        },
        "protectedSettings": {
            "commandToExecute": "myExecutionCommand",
            "storageAccountName": "myStorageAccountName",
            "storageAccountKey": "myStorageAccountKey",
            "managedIdentity" : {},
            "fileUris": [
                "script location"
            ]
        }
    }
}

Hinweis

Die Eigenschaft managedIdentitydarf nicht in Verbindung mit der Eigenschaft storageAccountName oder storageAccountKey verwendet werden.

Auf einem virtuellen Computer kann jeweils nur eine Version einer Erweiterung installiert werden. Das zweimalige Angeben eines benutzerdefinierten Skripts in derselben Azure Resource Manager-Vorlage für denselben virtuellen Computer führt zu einem Fehler.

Dieses Schema kann in der VM-Ressource oder als eigenständige Ressource verwendet werden. Der Name der Ressource muss das Format virtualMachineName/extensionName aufweisen, wenn diese Erweiterung als eigenständige Ressource in der Azure Resource Manager-Vorlage verwendet wird.

Eigenschaftswerte

Name Wert oder Beispiel Datentyp
apiVersion 2015-06-15 date
publisher Microsoft.Compute Zeichenfolge
type CustomScriptExtension Zeichenfolge
typeHandlerVersion 1.10 INT
fileUris https://raw.githubusercontent.com/Microsoft/dotnet-core-sample-templates/master/dotnet-core-music-windows/scripts/configure-music-app.ps1 array
timestamp 123456789 32-bit integer
commandToExecute powershell -ExecutionPolicy Unrestricted -File configure-music-app.ps1 Zeichenfolge
storageAccountName examplestorageacct Zeichenfolge
storageAccountKey TmJK/1N3AbAZ3q/+hOXoi/l73zOqsaxXDhqa9Y83/v5UpXQp2DQIBuv2Tifp60cE/OaHsJZmQZ7teQfczQj8hg== Zeichenfolge
managedIdentity { } oder { "clientId": "31b403aa-c364-4240-a7ff-d85fb6cd7232" } oder { "objectId": "12dd289c-0583-46e5-b9b4-115d5c19ef4b" } JSON-Objekt

Hinweis

Bei Eigenschaftennamen wird zwischen Groß- und Kleinschreibung unterschieden. Um Bereitstellungsprobleme zu vermeiden, verwenden Sie die Namen wie hier gezeigt.

Details zu Eigenschaftswerten

Eigenschaft Optional oder erforderlich Details
fileUris Optional URLs für Dateien, die heruntergeladen werden sollen. Wenn URLs vertraulich sind (z. B. wenn sie Schlüssel enthalten), sollte dieses Feld in protectedSettings angegeben werden.
commandToExecute Erforderlich Das auszuführende Einstiegspunktskript. Verwenden Sie diese Eigenschaft, wenn der Befehl Geheimnisse (z. B. Kennwörter) enthält oder die Datei-URIs vertraulich sind.
timestamp Optional Ändern Sie diesen Wert nur, um eine erneute Skriptausausführung auszulösen. Jeder ganzzahlige Wert ist akzeptabel, solange er sich vom vorherigen Wert unterscheidet.
storageAccountName Optional Der Name des Speicherkontos. Wenn Sie Speicheranmeldeinformationen angeben, muss es sich bei allen fileUris-Werten um URLs für Azure-Blobs handeln.
storageAccountKey Optional Der Zugriffsschlüssel des Speicherkontos
managedIdentity Optional Die verwaltete Identität zum Herunterladen von Dateien:

clientId (optional, Zeichenfolge): die Client-ID der verwalteten Identität

objectId (optional, Zeichenfolge): die Objekt-ID der verwalteten Identität

Sie können die folgenden Werte entweder in öffentlichen oder geschützten Einstellungen festlegen. Die Erweiterung lehnt jede Konfiguration ab, bei der diese Werte sowohl in öffentlichen als auch in geschützten Einstellungen festgelegt sind.

  • commandToExecute
  • fileUris

Die Verwendung öffentlicher Einstellungen kann zwar beim Debuggen hilfreich sein, es wird jedoch empfohlen, geschützte Einstellungen zu verwenden.

Öffentliche Einstellungen werden in Klartext an den virtuellen Computer gesendet, auf dem das Skript ausgeführt wird. Geschützte Einstellungen werden mit einem Schlüssel verschlüsselt, der nur Azure und dem virtuellen Computer bekannt ist. Die Einstellungen werden auf dem virtuellen Computer so gespeichert, wie gesendet wurden. Das heißt, wenn die Einstellungen verschlüsselt wurden, werden sie verschlüsselt auf dem virtuellen Computer gespeichert. Das Zertifikat, das zum Entschlüsseln der verschlüsselten Werte verwendet wird, ist auf dem virtuellen Computer gespeichert. Das Zertifikat wird auch verwendet, um Einstellungen (falls erforderlich) zur Laufzeit zu entschlüsseln.

Eigenschaft: managedIdentity

Hinweis

Diese Eigenschaft muss nur in geschützten Einstellungen angegeben werden.

Die benutzerdefinierte Skripterweiterung (Version 1.10 und höher) unterstützt verwaltete Identitäten zum Herunterladen von Dateien von URLs, die in der Einstellung fileUris angegeben sind. So kann die benutzerdefinierte Skripterweiterung auf private Azure Storage-Blobs oder -Container zugreifen, ohne dass der Benutzer Geheimnisse wie SAS-Token oder Speicherkontoschlüssel übergeben muss.

Um dieses Feature verwenden zu können, muss der Benutzer der VM oder VM-Skalierungsgruppe, auf der die benutzerdefinierte Skripterweiterung ausgeführt werden soll, eine vom System zugewiesene oder vom Benutzer zugewiesene Identität hinzufügen. Der Benutzer muss anschließend der verwalteten Identität Zugriff auf den Azure Storage-Container oder -Blob gewähren.

Um die vom System zugewiesene Identität für die Ziel-VM oder die VM-Skalierungsgruppe zu verwenden, legen Sie managedidentity auf ein leeres JSON-Objekt fest.

Beispiel:

{
  "fileUris": ["https://mystorage.blob.core.windows.net/privatecontainer/script1.ps1"],
  "commandToExecute": "powershell.exe script1.ps1",
  "managedIdentity" : {}
}

Um die vom Benutzer zugewiesene Identität für die Ziel-VM oder die VM-Skalierungsgruppe zu verwenden, konfigurieren Sie managedidentity mit der Client-ID oder der Objekt-ID der verwalteten Identität.

Beispiele:

{
  "fileUris": ["https://mystorage.blob.core.windows.net/privatecontainer/script1.ps1"],
  "commandToExecute": "powershell.exe script1.ps1",
  "managedIdentity" : { "clientId": "31b403aa-c364-4240-a7ff-d85fb6cd7232" }
}
{
  "fileUris": ["https://mystorage.blob.core.windows.net/privatecontainer/script1.ps1"],
  "commandToExecute": "powershell.exe script1.ps1",
  "managedIdentity" : { "objectId": "12dd289c-0583-46e5-b9b4-115d5c19ef4b" }
}

Hinweis

Die Eigenschaft managedIdentitydarf nicht in Verbindung mit der Eigenschaft storageAccountName oder storageAccountKey verwendet werden.

Bereitstellung von Vorlagen

Sie können Azure-VM-Erweiterungen mithilfe von Azure Resource Manager-Vorlagen bereitstellen. Das im vorherigen Abschnitt erläuterte JSON-Schema kann in einer Azure Resource Manager-Vorlage zum Ausführen der benutzerdefinierten Skripterweiterung während der Bereitstellung der Vorlage verwendet werden. Die folgenden Beispiele veranschaulichen die Verwendung der benutzerdefinierte Skripterweiterung:

PowerShell-Bereitstellung

Mit dem Befehl Set-AzVMCustomScriptExtension können Sie die benutzerdefinierte Skripterweiterung zu einem vorhandenen virtuellen Computer hinzufügen. Weitere Informationen finden Sie unter Set-AzVMCustomScriptExtension.

Set-AzVMCustomScriptExtension -ResourceGroupName <resourceGroupName> `
    -VMName <vmName> `
    -Location myLocation `
    -FileUri <fileUrl> `
    -Run 'myScript.ps1' `
    -Name DemoScriptExtension

Weitere Beispiele

Verwenden mehrerer Skripts

In diesem Beispiel verwenden Sie drei Skripts, um Ihren Server zu erstellen. Die Eigenschaft commandToExecute ruft das erste Skript auf. Anschließend haben Sie Optionen zum Aufrufen der anderen Skripts. Beispielsweise könnten Sie über ein Masterskript die Ausführung steuern und die richtige Fehlerbehandlung, Protokollierung und Zustandsverwaltung sicherstellen. Die Skripts werden zum Ausführen auf den lokalen Computer heruntergeladen.

In 1_Add_Tools.ps1 würden Sie beispielsweise 2_Add_Features.ps1 aufrufen, indem Sie .\2_Add_Features.ps1 zum Skript hinzufügen. Sie würden diesen Vorgang für die anderen Skripts wiederholen, die Sie in $settings definieren.

$fileUri = @("https://xxxxxxx.blob.core.windows.net/buildServer1/1_Add_Tools.ps1",
"https://xxxxxxx.blob.core.windows.net/buildServer1/2_Add_Features.ps1",
"https://xxxxxxx.blob.core.windows.net/buildServer1/3_CompleteInstall.ps1")

$settings = @{"fileUris" = $fileUri};

$storageAcctName = "xxxxxxx"
$storageKey = "1234ABCD"
$protectedSettings = @{"storageAccountName" = $storageAcctName; "storageAccountKey" = $storageKey; "commandToExecute" = "powershell -ExecutionPolicy Unrestricted -File 1_Add_Tools.ps1"};

#run command
Set-AzVMExtension -ResourceGroupName <resourceGroupName> `
    -Location <locationName> `
    -VMName <vmName> `
    -Name "buildserver1" `
    -Publisher "Microsoft.Compute" `
    -ExtensionType "CustomScriptExtension" `
    -TypeHandlerVersion "1.10" `
    -Settings $settings `
    -ProtectedSettings $protectedSettings;

Ausführen von Skripts über eine lokale Freigabe

In diesem Beispiel können Sie einen lokalen Server Message Block (SMB) für Ihren Skriptspeicherort verwenden. Sie müssen dann keine weiteren Einstellungen mit Ausnahme von commandToExecute bereitstellen.

$protectedSettings = @{"commandToExecute" = "powershell -ExecutionPolicy Unrestricted -File \\filesvr\build\serverUpdate1.ps1"};

Set-AzVMExtension -ResourceGroupName <resourceGroupName> `
    -Location <locationName> `
    -VMName <vmName> `
    -Name "serverUpdate"
    -Publisher "Microsoft.Compute" `
    -ExtensionType "CustomScriptExtension" `
    -TypeHandlerVersion "1.10" `
    -ProtectedSettings $protectedSettings

Mehrmaliges Ausführen eines benutzerdefinierten Skripts mithilfe der CLI

Der Handler für die benutzerdefinierte Skripterweiterung verhindert die erneute Ausführung eines Skripts, wenn genau dieselben Einstellungen übergeben wurden. Dieses Verhalten verhindert eine versehentliche erneute Ausführung, was zu unerwartetem Verhalten führen kann, wenn das Skript nicht idempotent ist. Sie können überprüfen, ob der Handler die erneute Ausführung blockiert hat, indem Sie C:\WindowsAzure\Logs\Plugins\Microsoft.Compute.CustomScriptExtension<HandlerVersion>CustomScriptHandler.log anzeigen und nach einer Warnung wie der folgenden suchen:

Current sequence number, <SequenceNumber>, is not greater than the sequence number of the most recently executed configuration. Exiting...

Wenn Sie die benutzerdefinierte Skripterweiterung mehrmals ausführen möchten, ist dies nur unter den folgenden Bedingungen möglich:

  • Der Parameter Name der Erweiterung ist identisch mit dem der vorherigen Bereitstellung der Erweiterung.
  • Sie haben die Konfiguration aktualisiert. Sie können dem Befehl eine dynamische Eigenschaft hinzufügen, z. B. einen Zeitstempel. Wenn der Handler eine Änderung an den Konfigurationseinstellungen erkennt, wertet er dies als expliziten Wunsch, das Skript erneut auszuführen.

Alternativ können Sie die Eigenschaft ForceUpdateTag auf true festlegen.

Verwenden von Invoke-WebRequest

Wenn Sie Invoke-WebRequest in Ihrem Skript verwenden, müssen Sie den Parameter -UseBasicParsing angeben. Wenn Sie den Parameter nicht angeben, erhalten Sie beim Überprüfen des detaillierten Status den folgenden Fehler:

The response content cannot be parsed because the Internet Explorer engine is not available, or Internet Explorer's first-launch configuration is not complete. Specify the UseBasicParsing parameter and try again.

VM-Skalierungsgruppen

Wenn Sie die benutzerdefinierte Skripterweiterung über das Azure-Portal bereitstellen, haben Sie keine Kontrolle über den Ablauf des SAS-Tokens für den Zugriff auf das Skript in Ihrem Speicherkonto. Aus diesem Grund funktioniert zwar die erste Bereitstellung, aber wenn das SAS-Token des Speicherkontos abläuft, führen nachfolgende Skalierungsvorgänge zu Fehlern, da die benutzerdefinierte Skripterweiterung nicht mehr auf das Speicherkonto zugreifen kann.

Es wird empfohlen, PowerShell, die Azure-Befehlszeilenschnittstelle oder eine Azure Resource Manager-Vorlage zu verwenden, wenn Sie die benutzerdefinierte Skripterweiterung in einer VM-Skalierungsgruppe bereitstellen. Auf diese Weise können Sie eine verwaltete Identität verwenden oder den Ablauf des SAS-Tokens für den Zugriff auf das Skript in Ihrem Speicherkonto direkt steuern.

Problembehandlung und Support

Daten zum Status von Erweiterungsbereitstellungen können aus dem Azure-Portal und über das Azure PowerShell-Modul abgerufen werden. Führen Sie den folgenden Befehl aus, um den Bereitstellungsstatus von Erweiterungen für einen virtuellen Computer anzuzeigen:

Get-AzVMExtension -ResourceGroupName <resourceGroupName> -VMName <vmName> -Name myExtensionName

Die Ausgabe der Erweiterung wird in Dateien im folgenden Ordner auf dem virtuellen Zielcomputer protokolliert:

C:\WindowsAzure\Logs\Plugins\Microsoft.Compute.CustomScriptExtension

Die angegebenen Dateien werden in den folgenden Ordner auf dem virtuellen Zielcomputer heruntergeladen:

C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.*\Downloads\<n>

Im vorherigen Pfad ist <n> eine dezimale ganze Zahl, die sich zwischen Ausführungen der Erweiterung ändern kann. Der Wert 1.* entspricht dem tatsächlichen aktuellen typeHandlerVersion-Wert der Erweiterung. Das tatsächliche Verzeichnis könnte z.B. folgendermaßen lauten: C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.8\Downloads\2.

Beim Ausführen des Befehls commandToExecute legt die Erweiterung dieses Verzeichnis (z. B. ...\Downloads\2) als aktuelles Arbeitsverzeichnis fest. Dieser Prozess ermöglicht die Verwendung relativer Pfade, um die heruntergeladenen Dateien mithilfe der fileURIs-Eigenschaft aufzufinden. Beispiele für heruntergeladene Dateien:

URI in fileUris Relativer Speicherort für Downloads Absoluter Speicherort für Downloads1
https://someAcct.blob.core.windows.net/aContainer/scripts/myscript.ps1 ./scripts/myscript.ps1 C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.8\Downloads\2\scripts\myscript.ps1
https://someAcct.blob.core.windows.net/aContainer/topLevel.ps1 ./topLevel.ps1 C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.8\Downloads\2\topLevel.ps1

1 Absolute Verzeichnispfade ändern sich während der Lebensdauer eines virtuellen Computers, nicht jedoch innerhalb einer einzelnen Ausführung der benutzerdefinierte Skripterweiterung.

Da sich der absolute Downloadpfad im Lauf der Zeit ändern kann, empfiehlt es sich, in der Zeichenfolge commandToExecute nach Möglichkeit relative Pfade zu Skripts und Dateien zu verwenden. Beispiel:

"commandToExecute": "powershell.exe . . . -File \"./scripts/myscript.ps1\""

Pfadinformationen nach dem ersten URI-Segment werden für Dateien beibehalten, die über die Eigenschaftenliste fileUris heruntergeladen werden. Wie in der Tabelle unten gezeigt, werden heruntergeladene Dateien Unterverzeichnissen für den Download zugeordnet, um die Struktur der fileUris-Werte widerzuspiegeln.

Support

Wenn Sie Hilfe zu einem Teil dieses Artikels benötigen, können Sie sich unter Azure-Communitysupport an die Azure-Experten wenden.

Sie können auch einen Azure-Supportfall zu erstellen. Rufen Sie die Azure-Support-Website auf, und wählen Sie Support erhaltenaus. Informationen zur Nutzung von Azure-Support finden Sie unter Häufig gestellte Fragen zum Azure-Support.