Extensión de la secuencia de comandos personalizada para Windows
La extensión de script personalizado descarga y ejecuta scripts en máquinas virtuales (VM) de Azure. Use esta extensión para la configuración posterior a la implementación, la instalación de software o cualquier otra tarea de configuración o administración. Puede descargar scripts de Azure Storage o GitHub, o bien proporcionárselos a Azure Portal en tiempo de ejecución de la extensión.
La extensión de script personalizado se integra con las plantillas de Azure Resource Manager. También puede ejecutarla mediante la CLI de Azure, Azure PowerShell, Azure Portal o la API de REST de Azure Virtual Machines.
En este artículo se describe cómo usar la extensión de script personalizado mediante el módulo de Azure PowerShell y las plantillas de Azure Resource Manager. También se proporcionan pasos para solucionar problemas de sistemas Windows.
Requisitos previos
Nota:
No use la extensión de script personalizado para ejecutar Update-AzVM
con la misma máquina virtual como su parámetro. La extensión esperará a sí misma.
Sistemas operativos Windows compatibles
SO Windows | x64 |
---|---|
Windows 10 | Compatible |
Windows 11 | Compatible |
Windows Server 2008 SP2 | Compatible |
Windows Server 2008 R2 | Compatible |
Windows Server 2012 | Compatible |
Windows Server 2012 R2 | Compatible |
Windows Server 2016 | Compatible |
Windows Server 2016 Core | Compatible |
Windows Server 2019 | Compatible |
Windows Server 2019 Core | Compatible |
Windows Server 2022 | Compatible |
Windows Server 2022 Core | Compatible |
Ubicación de los scripts
Puede establecer la extensión de modo que use las credenciales de Azure Blob Storage a fin de acceder a Azure Blob Storage. La ubicación del script puede ser cualquier lugar, siempre y cuando la máquina virtual pueda enrutarse a ese punto de conexión, por ejemplo, GitHub o un servidor de archivos interno.
Conectividad de Internet
Para descargar un script externamente, por ejemplo, desde GitHub o Azure Storage, debe abrir puertos adicionales de firewall o de grupo de seguridad de red (NSG). Por ejemplo, si el script se encuentra en Azure Storage, puede permitir el acceso mediante etiquetas de servicio NSG de Azure para Storage.
La extensión de script personalizado no tiene ninguna manera de omitir la validación de certificados. Por lo tanto, si descarga desde una ubicación segura, por ejemplo, un certificado autofirmado, puede que obtenga errores como El certificado remoto no es válido según el procedimiento de validación. Asegúrese de que el certificado esté instalado correctamente en el almacén Entidades de certificación raíz de confianza de la máquina virtual.
Si el script está en un servidor local, es posible que tenga que abrir otros puertos de firewall o NSG.
Sugerencias
- La salida se limita a los últimos 4096 bytes.
- Los caracteres de escape correctos ayudarán a garantizar que las cadenas se analizan correctamente. Por ejemplo, siempre necesita dos barras diagonales inversas para escapar una sola barra diagonal inversa literal al tratar con rutas de acceso de archivo. Ejemplo:
{"commandToExecute": "C:\\Windows\\System32\\systeminfo.exe >> D:\\test.txt"}
- La mayor tasa de errores para esta extensión se debe a errores de sintaxis en el script. Compruebe que el script se ejecuta sin errores. Coloque otro registro en el script para facilitar la búsqueda de errores.
- Escriba scripts que sean idempotentes, para que si se ejecutan más de una vez accidentalmente no se produzcan cambios en el sistema.
- Asegúrese de que los scripts no requieran la intervención del usuario cuando se ejecutan.
- El script puede ejecutarse durante 90 minutos. Un valor superior a este provoca un error de aprovisionamiento de la extensión.
- No coloque reinicios dentro del script. Esta acción provoca problemas con otras extensiones que se estén instalando y la extensión no continúa después del reinicio.
- Si tiene un script que provoca un reinicio, antes de instalar aplicaciones y ejecutar scripts, programe el reinicio con una tarea programada de Windows o con herramientas como las extensiones DSC, Chef o Puppet.
- No ejecute un script que provoque la detención o actualización del agente de máquina virtual. Esto puede dejar la extensión en un estado de transición y provocar tiempo de espera.
- La extensión ejecuta un script solo una vez. Si quiere ejecutar un script en cada inicio, use la extensión para crear una tarea programada de Windows.
- Si quiere programar cuándo se va a ejecutar un script, use la extensión para crear una tarea programada de Windows.
- Cuando el script se esté ejecutando, solo verá un estado de extensión en transición desde Azure Portal o la CLI de Azure. Si quiere recibir actualizaciones de estado más frecuentes de un script en ejecución, cree su propia solución.
- La extensión de script personalizado no admite servidores proxy de forma nativa. Aun así, puede usar una herramienta de transferencia de archivos que admita servidores proxy dentro del script, como Invoke-WebRequest.
- Tenga en cuenta las ubicaciones de directorio no predeterminadas en las que se puedan basar los scripts o comandos. Aplique lógica para controlarlas.
- Asegúrese de que no tiene ninguna configuración personalizada en la clave del Registro
HKLM\SOFTWARE\Microsoft\Command Processor\AutoRun
(detallada aquí). Esto se desencadenaría durante la instalación o habilitación de la extensión de script personalizado y provocaría un error como'XYZ is not recognized as an internal or external command, operable program or batch file'
. - La extensión de script personalizado se ejecuta con la cuenta
LocalSystem
. - Si tiene previsto usar las propiedades
storageAccountName
ystorageAccountKey
, deben colocarse enprotectedSettings
. - Solo puede tener aplicada una versión de una extensión a la máquina virtual. Para ejecutar un segundo script personalizado, puede actualizar la extensión existente con una nueva configuración. Alternativamente, puede quitar la extensión de script personalizado y volver a aplicarla con el script actualizado
Esquema de extensión
La configuración de la extensión de script personalizado especifica aspectos como la ubicación del script y el comando que se ejecutará. Esta configuración se puede almacenar en archivos de configuración, o se puede especificar en la línea de comandos o en una plantilla de Azure Resource Manager.
Puede almacenar datos confidenciales en una configuración protegida, que se cifra y se descifra solo dentro de la máquina virtual. La configuración protegida es útil cuando el comando de ejecución incluye secretos, como una contraseña o una referencia a un archivo de firma de acceso compartido (SAS). Este es un ejemplo:
{
"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"
]
}
}
}
Nota
La propiedad managedIdentity
no debe usarse junto con la propiedad storageAccountName
o storageAccountKey
.
Solo se puede instalar una versión de una extensión en una máquina virtual a la vez. Se produce un error si se especifica dos veces un script personalizado en la misma plantilla de Azure Resource Manager para la misma máquina virtual.
Puede usar este esquema dentro del recurso de VM o como un recurso independiente. El nombre del recurso debe tener el formato virtualMachineName/extensionName si se usa esta extensión como recurso independiente en la plantilla de Azure Resource Manager.
Valores de propiedad
Nombre | Valor o ejemplo | Tipo de datos |
---|---|---|
apiVersion | 2015-06-15 |
date |
publisher | Microsoft.Compute |
string |
type | CustomScriptExtension |
string |
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 |
Entero de 32 bits |
commandToExecute | powershell -ExecutionPolicy Unrestricted -File configure-music-app.ps1 |
string |
storageAccountName | examplestorageacct |
string |
storageAccountKey | TmJK/1N3AbAZ3q/+hOXoi/l73zOqsaxXDhqa9Y83/v5UpXQp2DQIBuv2Tifp60cE/OaHsJZmQZ7teQfczQj8hg== |
string |
managedIdentity | { } , { "clientId": "31b403aa-c364-4240-a7ff-d85fb6cd7232" } o { "objectId": "12dd289c-0583-46e5-b9b4-115d5c19ef4b" } |
Objeto JSON |
Nota
Los nombres de propiedad distinguen entre mayúsculas y minúsculas. Para evitar problemas de implementación, use los nombres como se muestran aquí.
Detalles del valor de propiedad
Propiedad | Opcional u obligatoria | Detalles |
---|---|---|
fileUris | Opcionales | Direcciones URL de los archivos que se descargarán. Si las direcciones URL son confidenciales, por ejemplo, contienen claves, este campo debe especificarse en protectedSettings . |
commandToExecute | Obligatorio | Script de punto de entrada que se ejecutará. Use esta propiedad si el comando contiene secretos, como contraseñas, o si los URI de archivo son confidenciales. |
timestamp | Opcionales | Cambie este valor solo para desencadenar una nueva ejecución del script. Cualquier valor entero es aceptable, siempre y cuando sea diferente del valor anterior. |
storageAccountName | Opcionales | Nombre de la cuenta de almacenamiento. Si especifica credenciales de almacenamiento, todos los valores de fileUris deben ser direcciones URL de blobs de Azure. |
storageAccountKey | Opcionales | Clave de acceso de la cuenta de almacenamiento. |
managedIdentity | Opcionales | La identidad administrada para descargar archivos. Los valores válidos son clientId (opcional, cadena), que es el identificador de cliente de la identidad administrada y objectId (opcional, cadena), que es el identificador de objeto de la identidad administrada. |
La configuración pública se envía en texto no cifrado a la máquina virtual donde se ejecuta el script. La configuración protegida se cifra con una clave que solo conocen Azure y la máquina virtual. La configuración se guarda en la máquina virtual a medida que se envía. Es decir, si la configuración se ha cifrado, se guarda cifrada en la máquina virtual. El certificado que se usa para descifrar los valores cifrados se almacena en la máquina virtual. El certificado también se usa para descifrar la configuración (si es necesario) en tiempo de ejecución.
El empleo de la configuración pública puede resultar útil para la depuración, pero se recomienda usar la configuración protegida.
Puede establecer los siguientes valores en la configuración pública o en la protegida. La extensión rechaza cualquier configuración en la que estos valores estén establecidos tanto en la configuración pública como en la protegida.
commandToExecute
fileUris
Propiedad: managedIdentity
Nota
Esta propiedad debe especificarse solo en la configuración protegida.
La extensión de script personalizado, versión 1.10 y posteriores, admite identidades administradas para descargar archivos de direcciones URL proporcionadas en la configuración fileUris
. La propiedad permite a la extensión de script personalizado acceder a blobs o contenedores privados de Azure Storage sin que el usuario tenga que enviar secretos como tokens de SAS o claves de cuenta de almacenamiento.
Para usar esta característica, agregue una identidad asignada por el sistema o asignada por el usuario a la máquina virtual o al conjunto de escalado de máquinas virtuales donde se ejecuta la extensión de script personalizado. Después, conceda a la identidad administrada acceso al contenedor o blob de Azure Storage.
Para usar la identidad asignada por el sistema en la máquina virtual o conjunto de escalado de máquinas virtuales de destino, establezca el campo managedidentity
en un objeto JSON vacío.
{
"fileUris": ["https://mystorage.blob.core.windows.net/privatecontainer/script1.ps1"],
"commandToExecute": "powershell.exe script1.ps1",
"managedIdentity" : {}
}
Para usar la identidad asignada por el usuario en la máquina virtual o el conjunto de escalado de máquinas virtuales de destino, configure el campo managedidentity
con el id. de cliente o el id. de objeto de la identidad administrada.
{
"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" }
}
Nota
La propiedad managedIdentity
no debe usarse junto con la propiedad storageAccountName
o storageAccountKey
.
Implementación de plantilla
Puede implementar extensiones de VM de Azure mediante plantillas de Azure Resource Manager. El esquema JSON detallado en la sección anterior se puede usar en una plantilla de Azure Resource Manager para ejecutar la extensión de script personalizado durante la implementación de la plantilla. En los ejemplos siguientes se muestra cómo usar la extensión de script personalizado:
- Implementación de extensiones de máquina virtual con plantillas de Azure Resource Manager
- Implementación de aplicaciones de dos niveles en Windows y Azure SQL Database
Implementación de PowerShell
Puede usar el comando Set-AzVMCustomScriptExtension
para agregar la extensión de script personalizado a una máquina virtual existente. Para más información, consulte Set-AzVMCustomScriptExtension.
Set-AzVMCustomScriptExtension -ResourceGroupName <resourceGroupName> `
-VMName <vmName> `
-Location myLocation `
-FileUri <fileUrl> `
-Run 'myScript.ps1' `
-Name DemoScriptExtension
Ejemplos
Empleo de varios scripts
En este ejemplo se usan tres scripts para compilar el servidor. La propiedad commandToExecute
llama al primer script. Después, dispone de opciones sobre cómo se llama a los demás. Por ejemplo, puede tener un script principal que controla la ejecución con el control de errores, el registro y la administración de estado adecuados. Los scripts se descargan en el equipo local para su ejecución.
Por ejemplo, en 1_Add_Tools.ps1, llamaría a 2_Add_Features.ps1 mediante la adición de .\2_Add_Features.ps1
al script. Repita este proceso para los demás scripts que defina en $settings
.
$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;
Ejecutar scripts desde un recurso compartido local
En este ejemplo, es posible que quiera usar un servidor de Bloque de mensajes del servidor (SMB) local para la ubicación del script. No es necesario proporcionar después ningún otro valor de configuración, excepto commandToExecute
.
$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
Ejecución de un script personalizado más de una vez mediante la CLI
El controlador de extensión de script personalizado impide volver a ejecutar un script si se ha pasado exactamente la misma configuración. Este comportamiento impide que se vuelva a ejecutar accidentalmente, lo que podría provocar comportamientos inesperados si el script no es idempotente. Para confirmar si el controlador bloqueó el nueva ejecución, examine C:\WindowsAzure\Logs\Plugins\Microsoft.Compute.CustomScriptExtension\<HandlerVersion>\CustomScriptHandler.log*
. Busque una advertencia como esta:
Current sequence number, <SequenceNumber>, is not greater than the sequence number
of the most recently executed configuration. Exiting...
Si quiere ejecutar la extensión de script personalizado más de una vez, puede hacerlo únicamente si se cumplen las condiciones siguientes:
- El parámetro
Name
de la extensión coincide con la implementación anterior de la extensión. - Ha actualizado la configuración. Puede agregar una propiedad dinámica en el comando, como una marca de tiempo. Si el controlador detecta un cambio en las opciones de configuración, lo considera un deseo explícito de volver a ejecutar el script.
También puede establecer la propiedad ForceUpdateTag en true
.
Empleo de Invoke-WebRequest
Si usa Invoke-WebRequest en el script, debe especificar el parámetro -UseBasicParsing
. Si no especifica el parámetro, recibe el siguiente error al comprobar el estado detallado:
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.
Virtual Machine Scale Sets
Si implementa la extensión de script personalizado desde Azure Portal, no tiene control sobre la expiración del token de SAS para acceder al script en la cuenta de almacenamiento. La implementación inicial funciona, pero cuando expira el token de SAS de la cuenta de almacenamiento, se produce un error en cualquier operación de escalado posterior porque la extensión de script personalizado ya no puede acceder a la cuenta de almacenamiento.
Se recomienda usar PowerShell, la CLI de Azure o una plantilla de Azure Resource Manager al implementar la extensión de script personalizado en un conjunto de escalado de máquinas virtuales. De este modo, puede elegir usar una identidad administrada o tener control directo de la expiración del token de SAS para acceder al script en la cuenta de almacenamiento durante el tiempo que necesite.
Solución de problemas y asistencia
Puede recuperar los datos sobre el estado de las implementaciones de extensiones desde Azure Portal y mediante el módulo de Azure PowerShell. Para ver el estado de implementación de las extensiones de una máquina virtual, ejecute el comando siguiente:
Get-AzVMExtension -ResourceGroupName <resourceGroupName> `
-VMName <vmName> -Name myExtensionName
La salida de la extensión se registra en archivos que se encuentran en la siguiente carpeta de la máquina virtual de destino:
C:\WindowsAzure\Logs\Plugins\Microsoft.Compute.CustomScriptExtension
Los archivos especificados se descargan en la siguiente carpeta de la máquina virtual de destino:
C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.*\Downloads\<n>
En la ruta de acceso anterior, <n>
es un entero decimal que puede cambiar entre las ejecuciones de la extensión. El valor 1.*
coincide con el valor typeHandlerVersion
actual y real de la extensión. Por ejemplo, el directorio real podría ser C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.8\Downloads\2
.
Cuando se ejecute el comando commandToExecute
, la extensión establece este directorio, por ejemplo, ...\Downloads\2
, como directorio de trabajo actual. Este proceso permite el uso de rutas de acceso relativas para buscar los archivos descargados mediante la propiedad fileURIs
. Estos son algunos ejemplos de archivos descargados:
URI en fileUris |
Ubicación de descarga relativa | Ubicación de descarga absoluta |
---|---|---|
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 |
Las rutas de acceso absolutas al directorio cambian a lo largo del ciclo de vida de la máquina virtual, pero no durante una ejecución única de la extensión de script personalizado.
Dado que la ruta de acceso absoluta de descarga podría variar con el paso del tiempo, es mejor optar por rutas de acceso relativas de archivo o script en la cadena commandToExecute
, siempre que sea posible. Por ejemplo:
"commandToExecute": "powershell.exe . . . -File \"./scripts/myscript.ps1\""
Se conserva la información de la ruta de acceso tras el primer segmento de URI de los archivos descargados mediante la lista de propiedades fileUris
. Como se muestra en la tabla anterior, los archivos descargados se asignan en los subdirectorios de descarga para reflejar la estructura de los valores fileUris
.
Soporte técnico
Si necesita ayuda con alguna parte de este artículo, póngase en contacto con los expertos de Azure en el Soporte técnico de la comunidad de Azure.
Vaya al sitio Soporte técnico de Azure y seleccione Obtener soporte técnico para registrar un incidente de soporte técnico de Azure.
Para más información sobre el uso del soporte técnico de Azure, lea las preguntas más frecuentes.