在 Linux 虚拟机上使用 Azure 自定义脚本扩展版本 2Use the Azure Custom Script Extension Version 2 with Linux virtual machines

自定义脚本扩展版本 2 在 Azure 虚拟机上下载和运行脚本。The Custom Script Extension Version 2 downloads and runs scripts on Azure virtual machines. 此扩展适用于部署后配置、软件安装或其他任何配置/管理任务。This extension is useful for post-deployment configuration, software installation, or any other configuration/management task. 可以从 Azure 存储或其他可访问的 Internet 位置下载脚本,或者将脚本提供给扩展运行时。You can download scripts from Azure Storage or another accessible internet location, or you can provide them to the extension runtime.

将自定义脚本扩展与 Azure 资源管理器模板集成。The Custom Script Extension integrates with Azure Resource Manager templates. 也可使用 Azure CLI、PowerShell 或 Azure 虚拟机 REST API 来运行它。You can also run it by using Azure CLI, PowerShell, or the Azure Virtual Machines REST API.

本文详细介绍如何使用 Azure CLI 中的自定义脚本扩展以及如何使用 Azure 资源管理器模板运行扩展。This article details how to use the Custom Script Extension from Azure CLI, and how to run the extension by using an Azure Resource Manager template. 本文还提供针对 Linux 系统的疑难解答步骤。This article also provides troubleshooting steps for Linux systems.

存在两个 Linux 自定义脚本扩展:There are two Linux Custom Script Extensions:

  • 版本 1 - Microsoft.OSTCExtensions.CustomScriptForLinuxVersion 1 - Microsoft.OSTCExtensions.CustomScriptForLinux
  • 版本 2 - Microsoft.Azure.Extensions.CustomScriptVersion 2 - Microsoft.Azure.Extensions.CustomScript

请切换新部署和现有部署,改用新的版本 2。Please switch new and existing deployments to use the new version 2 instead. 新版本可作为一个简易的替代版本。The new version is intended to be a drop-in replacement. 因此,迁移时只需更改名称和版本,无需更改扩展配置。Therefore, the migration is as easy as changing the name and version, you do not need to change your extension configuration.

操作系统Operating System

适用于 Linux 的自定义脚本扩展将在扩展支持的扩展 OS 上运行,有关详细信息,请参阅此文The Custom Script Extension for Linux will run on the extension supported extension OS's, for more information, see this article.

脚本位置Script Location

可使用扩展,利用 Azure Blob 存储凭据来访问 Azure Blob 存储。You can use the extension to use your Azure Blob storage credentials, to access Azure Blob storage. 或者,脚本位置可以是任何位置,只要 VM 可以路由到该终结点(如 GitHub、内部文件服务器等)即可。Alternatively, the script location can be any where, as long as the VM can route to that end point, such as GitHub, internal file server etc.

Internet 连接Internet Connectivity

如果需要从外部(例如 GitHub 或 Azure 存储)下载脚本,则需要打开其他防火墙/网络安全组端口。If you need to download a script externally such as GitHub or Azure Storage, then additional firewall/Network Security Group ports need to be opened. 例如,如果脚本位于 Azure 存储中,可以使用存储的 Azure NSG 服务标记来允许访问。For example if your script is located in Azure Storage, you can allow access using Azure NSG Service Tags for Storage.

如果脚本位于本地服务器上,则可能仍需要打开其他防火墙/网络安全组端口。If your script is on a local server, then you may still need additional firewall/Network Security Group ports need to be opened.

提示和技巧Tips and Tricks

  • 脚本中的语法错误会导致此扩展失败率最高,应测试脚本运行正确无误,同时在脚本中添加其他日志记录,以便更轻松地找到失败位置。The highest failure rate for this extension is due to syntax errors in the script, test the script runs without error, and also put in additional logging into the script to make it easier to find where it failed.
  • 编写幂等性的脚本,这样一来,如果脚本意外多次运行,将不会导致系统更改。Write scripts that are idempotent, so if they get run again more than once accidentally, it will not cause system changes.
  • 确保这些脚本在运行时不需要用户输入。Ensure the scripts do not require user input when they run.
  • 脚本可以运行 90 分钟,若运行时间超过 90 分钟,将导致扩展的预配失败。There is 90 mins allowed for the script to run, anything longer will result in a failed provision of the extension.
  • 请勿将 reboot 置于脚本中,这会导致正在安装的其他扩展出现问题,并且在重启后,该扩展将不会继续。Do not put reboots inside the script, this will cause issues with other extensions that are being installed, and post reboot, the extension will not continue after the restart.
  • 如果脚本会导致重启,则安装应用程序并运行脚本等。应该使用 Cron 作业或者使用 DSC 或 Chef、Puppet 扩展等工具来计划重启。If you have a script that will cause a reboot, then install applications and run scripts etc. You should schedule the reboot using a Cron job, or using tools such as DSC, or Chef, Puppet extensions.
  • 该扩展只会运行一个脚本一次,如果想要在每次启动时运行一个脚本,则可以使用 cloud-init 映像Scripts Per Boot 模块。The extension will only run a script once, if you want to run a script on every boot, then you can use cloud-init image and use a Scripts Per Boot module. 或者,可以使用脚本创建 SystemD 服务单元。Alternatively, you can use the script to create a SystemD service unit.
  • 只能向 VM 应用一个扩展版本。You can only have one version of an extension applied to the VM. 若要运行另一个自定义脚本,需要删除自定义脚本扩展,并使用更新的脚本再次重新应用该扩展。In order to run a second custom script, you need to remove the custom script extension and reapply it again with the updated script.
  • 如果想要计划脚本何时运行,应使用扩展创建一个 Cron 作业。If you want to schedule when a script will run, you should use the extension to create a Cron job.
  • 脚本运行时,Azure 门户或 CLI 中只会显示“正在转换”扩展状态。When the script is running, you will only see a 'transitioning' extension status from the Azure portal or CLI. 如果希望更频繁地更新正在运行的脚本的状态,需要创建自己的解决方案。If you want more frequent status updates of a running script, you will need to create your own solution.
  • 自定义脚本扩展本身不支持代理服务器,但可以使用脚本中支持代理服务器的文件传输工具,如 Curl。Custom Script extension does not natively support proxy servers, however you can use a file transfer tool that supports proxy servers within your script, such as Curl.
  • 请注意脚本或命令可能依赖的非默认目录位置,按逻辑对其进行处理。Be aware of non default directory locations that your scripts or commands may rely on, have logic to handle this.
  • 将自定义脚本部署到生产 VMSS 实例时,建议通过 json 模板进行部署,并将脚本存储帐户存储在你可以控制 SAS 令牌的位置。When deploying custom script to production VMSS instances it is suggested to deploy via json template and store your script storage account where you have control over the SAS token.

扩展架构Extension schema

自定义脚本扩展配置指定脚本位置和要运行命令等设置。The Custom Script Extension configuration specifies things like script location and the command to be run. 可将此配置存储在配置文件中、在命令行中指定,或者在 Azure 资源管理器模板中指定该配置。You can store this configuration in configuration files, specify it on the command line, or specify it in an Azure Resource Manager template.

可将敏感数据存储在受保护的配置中,此配置经过加密,只能在虚拟机内部解密。You can store sensitive data in a protected configuration, which is encrypted and only decrypted inside the virtual machine. 当执行命令包含机密(例如密码)时,受保护的配置相当有用。The protected configuration is useful when the execution command includes secrets such as a password.

这些项目应视为敏感数据,并在扩展的受保护设置配置中指定。These items should be treated as sensitive data and specified in the extensions protected setting configuration. Azure VM 扩展的受保护设置数据已加密,并且只能在目标虚拟机上解密。Azure VM extension protected setting data is encrypted, and only decrypted on the target virtual machine.

{
  "name": "config-app",
  "type": "Extensions",
  "location": "[resourceGroup().location]",
  "apiVersion": "2019-03-01",
  "dependsOn": [
    "[concat('Microsoft.Compute/virtualMachines/', concat(variables('vmName'),copyindex()))]"
  ],
  "tags": {
    "displayName": "config-app"
  },
  "properties": {
    "publisher": "Microsoft.Azure.Extensions",
    "type": "CustomScript",
    "typeHandlerVersion": "2.1",
    "autoUpgradeMinorVersion": true,
    "settings": {
      "skipDos2Unix":false,
      "timestamp":123456789          
    },
    "protectedSettings": {
       "commandToExecute": "<command-to-execute>",
       "script": "<base64-script-to-execute>",
       "storageAccountName": "<storage-account-name>",
       "storageAccountKey": "<storage-account-key>",
       "fileUris": ["https://.."],
       "managedIdentity" : "<managed-identity-identifier>"
    }
  }
}

备注

managedIdentity 属性不能与 storageAccountName 或 storageAccountKey 属性结合使用managedIdentity property must not be used in conjunction with storageAccountName or storageAccountKey properties

属性值Property values

名称Name 值/示例Value / Example 数据类型Data Type
apiVersionapiVersion 2019-03-012019-03-01 datedate
publisherpublisher Microsoft.Compute.ExtensionsMicrosoft.Compute.Extensions stringstring
typetype CustomScriptCustomScript stringstring
typeHandlerVersiontypeHandlerVersion 2.12.1 intint
fileUris(例如)fileUris (e.g) https://github.com/MyProject/Archive/MyPythonScript.py arrayarray
commandToExecute(例如)commandToExecute (e.g) python MyPythonScript.py <my-param1>python MyPythonScript.py <my-param1> stringstring
脚本script IyEvYmluL3NoCmVjaG8gIlVwZGF0aW5nIHBhY2thZ2VzIC4uLiIKYXB0IHVwZGF0ZQphcHQgdXBncmFkZSAteQo=IyEvYmluL3NoCmVjaG8gIlVwZGF0aW5nIHBhY2thZ2VzIC4uLiIKYXB0IHVwZGF0ZQphcHQgdXBncmFkZSAteQo= stringstring
skipDos2Unix(示例)skipDos2Unix (e.g) falsefalse booleanboolean
timestamp(示例)timestamp (e.g) 123456789123456789 32-bit integer32-bit integer
storageAccountName(例如)storageAccountName (e.g) examplestorageacctexamplestorageacct stringstring
storageAccountKey(例如)storageAccountKey (e.g) TmJK/1N3AbAZ3q/+hOXoi/l73zOqsaxXDhqa9Y83/v5UpXQp2DQIBuv2Tifp60cE/OaHsJZmQZ7teQfczQj8hg==TmJK/1N3AbAZ3q/+hOXoi/l73zOqsaxXDhqa9Y83/v5UpXQp2DQIBuv2Tifp60cE/OaHsJZmQZ7teQfczQj8hg== stringstring
managedIdentity(例如)managedIdentity (e.g) { } 或 { "clientId":"31b403aa-c364-4240-a7ff-d85fb6cd7232" } 或 { "objectId":"12dd289c-0583-46e5-b9b4-115d5c19ef4b" }{ } or { "clientId": "31b403aa-c364-4240-a7ff-d85fb6cd7232" } or { "objectId": "12dd289c-0583-46e5-b9b4-115d5c19ef4b" } json 对象json object

属性值详细信息Property value details

  • apiVersion:可以通过 Azure CLI 使用以下命令找到最新的 apiVersionaz provider list -o jsonapiVersion: The most up to date apiVersion can be found from Azure CLI using the following command az provider list -o json

  • skipDos2Unix:(可选,布尔值)跳过对基于脚本的文件 URL 或脚本进行的 dos2unix 转换。skipDos2Unix: (optional, boolean) skip dos2unix conversion of script-based file URLs or script.

  • timestamp(可选,32 位整数)仅当需要更改此字段的值来触发脚本的重新运行时,才使用此字段。timestamp (optional, 32-bit integer) use this field only to trigger a re-run of the script by changing value of this field. 任何整数值都是可以接受的,前提是必须不同于以前的值。Any integer value is acceptable; it must only be different than the previous value.

  • commandToExecute:(在脚本未设置的情况下为必需,字符串)要执行的入口点脚本。commandToExecute: (required if script not set, string) the entry point script to execute. 如果命令包含机密(例如密码),请改用此字段。Use this field instead if your command contains secrets such as passwords.

  • script:(在 commandToExecute 未设置的情况下为必需,字符串)base64 编码(可以选择执行 gzip 操作)的脚本,通过 /bin/sh 来执行。script: (required if commandToExecute not set, string)a base64 encoded (and optionally gzip'ed) script executed by /bin/sh.

  • fileUris:(可选,字符串数组)要下载的文件的 URL。fileUris: (optional, string array) the URLs for file(s) to be downloaded.

  • storageAccountName:(可选,字符串)存储帐户的名称。storageAccountName: (optional, string) the name of storage account. 如果指定存储凭据,所有 fileUris 都必须是 Azure Blob 的 URL。If you specify storage credentials, all fileUris must be URLs for Azure Blobs.

  • storageAccountKey:(可选,字符串)存储帐户的访问密钥storageAccountKey: (optional, string) the access key of storage account

  • managedIdentity:(可选,json 对象)用于下载文件的托管标识managedIdentity: (optional, json object) the managed identity for downloading file(s)

    • clientId:(可选,字符串)托管标识的客户端 IDclientId: (optional, string) the client ID of the managed identity
    • objectId:(可选,字符串)托管标识的对象 IDobjectId: (optional, string) the object ID of the managed identity

可以在公共设置或受保护设置中设置以下值,但扩展会拒绝任何同时在公共设置和受保护设置中设置以下值的配置。The following values can be set in either public or protected settings, the extension will reject any configuration where the values below are set in both public and protected settings.

  • commandToExecute
  • script
  • fileUris

虽然使用公共设置可能对调试很有用,但强烈建议使用受保护设置。Using public settings maybe useful for debugging, but it is strongly recommended that you use protected settings.

公共设置会以明文形式发送到将执行脚本的 VM。Public settings are sent in clear text to the VM where the script will be executed. 受保护设置使用只有 Azure 和 VM 知道的密钥进行加密。Protected settings are encrypted using a key known only to the Azure and the VM. 这些设置会在发送时保存到 VM 中,也就是说,如果设置已加密,则会在 VM 上加密保存。The settings are saved to the VM as they were sent, i.e. if the settings were encrypted they are saved encrypted on the VM. 用于对已加密值解密的证书存储在 VM 上,该证书用于在运行时对设置解密(如必要)。The certificate used to decrypt the encrypted values is stored on the VM, and used to decrypt settings (if necessary) at runtime.

属性:skipDos2UnixProperty: skipDos2Unix

默认值为 false,这意味着执行 dos2unix 转换。The default value is false, which means dos2unix conversion is executed.

旧版 CustomScript (Microsoft.OSTCExtensions.CustomScriptForLinux) 会将 \r\n 转换为 \n,从而将 DOS 文件自动转换为 UNIX 文件。The previous version of CustomScript, Microsoft.OSTCExtensions.CustomScriptForLinux, would automatically convert DOS files to UNIX files by translating \r\n to \n. 此转换仍然存在,并且默认为启用状态。This translation still exists, and is on by default. 此转换适用于从 fileUris 下载的所有文件或基于任何下述标准的脚本设置。This conversion is applied to all files downloaded from fileUris or the script setting based on any of the following criteria.

  • 如果扩展名为 .sh.txt.py.pl 之一,则会进行转换。If the extension is one of .sh, .txt, .py, or .pl it will be converted. 脚本设置将始终符合此条件,因为已经假定该脚本是使用 /bin/sh 执行的脚本,并且会在 VM 上将它另存为 script.sh。The script setting will always match this criteria because it is assumed to be a script executed with /bin/sh, and is saved as script.sh on the VM.
  • 如果文件以 #! 开头。If the file starts with #!.

将 skipDos2Unix 设置为 true 即可跳过 dos2unix 转换。The dos2unix conversion can be skipped by setting the skipDos2Unix to true.

{
  "fileUris": ["<url>"],
  "commandToExecute": "<command-to-execute>",
  "skipDos2Unix": true
}

属性:脚本Property: script

CustomScript 支持执行用户定义的脚本。CustomScript supports execution of a user-defined script. 可将 commandToExecute 和 fileUris 组合到单个设置中的脚本设置。The script settings to combine commandToExecute and fileUris into a single setting. 可以直接将脚本编码为设置,不必设置一个需要从 Azure 存储或 GitHub 主题下载的文件。Instead of the having to setup a file for download from Azure storage or GitHub gist, you can simply encode the script as a setting. 可以使用脚本来替换 commandToExecute 和 fileUris。Script can be used to replaced commandToExecute and fileUris.

脚本必须进行 base64 编码。The script must be base64 encoded. 可以选择对脚本执行 gzip 操作。The script can optionally be gzip'ed. 脚本设置可以用在公共设置或受保护的设置中。The script setting can be used in public or protected settings. 脚本参数数据的最大大小为 256 KB。The maximum size of the script parameter's data is 256 KB. 如果脚本超出此大小,则不会执行该脚本。If the script exceeds this size it will not be executed.

以保存到 /script.sh/ 文件的以下脚本为例。For example, given the following script saved to the file /script.sh/.

#!/bin/sh
echo "Updating packages ..."
apt update
apt upgrade -y

正确的 CustomScript 脚本设置可以使用以下命令的输出来构造。The correct CustomScript script setting would be constructed by taking the output of the following command.

cat script.sh | base64 -w0
{
  "script": "IyEvYmluL3NoCmVjaG8gIlVwZGF0aW5nIHBhY2thZ2VzIC4uLiIKYXB0IHVwZGF0ZQphcHQgdXBncmFkZSAteQo="
}

可以选择对脚本执行 gzip 操作,以便进一步缩小其大小(适用于大多数情况)。 (CustomScript 自动检测是否使用了 gzip 压缩。)(CustomScript auto-detects the use of gzip compression.)

cat script | gzip -9 | base64 -w 0

CustomScript 使用以下算法来执行脚本。CustomScript uses the following algorithm to execute a script.

  1. 断言脚本值的长度不得超过 256 KB。assert the length of the script's value does not exceed 256 KB.
  2. base64 对脚本的值进行解码base64 decode the script's value
  3. 尝试对 base64 解码的值执行 gunzip 操作attempt to gunzip the base64 decoded value
  4. 将解码(以及可以选择进行解压缩)的值写入磁盘 (/var/lib/waagent/custom-script/#/script.sh)write the decoded (and optionally decompressed) value to disk (/var/lib/waagent/custom-script/#/script.sh)
  5. 使用 _/bin/sh -c /var/lib/waagent/custom-script/#/script.sh 执行脚本。execute the script using _/bin/sh -c /var/lib/waagent/custom-script/#/script.sh.

属性:managedIdentityProperty: managedIdentity

备注

只应在受保护的设置中指定此属性。This property must be specified in protected settings only.

CustomScript(2.1 版及更高版本)支持使用托管标识从“fileUris”设置中提供的 URL 下载文件。CustomScript (version 2.1 onwards) supports managed identity for downloading file(s) from URLs provided in the "fileUris" setting. 它允许 CustomScript 访问 Azure 存储专用 Blob 或容器,而无需用户传递 SAS 令牌或存储帐户密钥等机密。It allows CustomScript to access Azure Storage private blobs or containers without the user having to pass secrets like SAS tokens or storage account keys.

若要使用此功能,用户必须将系统分配的用户分配的标识添加到需要运行 CustomScript 的 VM 或 VMSS,并授予托管标识访问 Azure 存储容器或 Blob 的权限To use this feature, the user must add a system-assigned or user-assigned identity to the VM or VMSS where CustomScript is expected to run, and grant the managed identity access to the Azure Storage container or blob.

若要在目标 VM/VMSS 上使用系统分配的标识,请将“managedidentity”字段设置为空的 json 对象。To use the system-assigned identity on the target VM/VMSS, set "managedidentity" field to an empty json object.

示例:Example:

{
  "fileUris": ["https://mystorage.blob.core.chinacloudapi.cn/privatecontainer/script1.sh"],
  "commandToExecute": "sh script1.sh",
  "managedIdentity" : {}
}

若要在目标 VM/VMSS 上使用用户分配的标识,请将“managedidentity”字段配置为托管标识的客户端 ID 或对象 ID。To use the user-assigned identity on the target VM/VMSS, configure "managedidentity" field with the client ID or the object ID of the managed identity.

示例:Examples:

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

备注

managedIdentity 属性不能与 storageAccountName 或 storageAccountKey 属性结合使用managedIdentity property must not be used in conjunction with storageAccountName or storageAccountKey properties

模板部署Template deployment

可使用 Azure Resource Manager 模板部署 Azure VM 扩展。Azure VM extensions can be deployed with Azure Resource Manager templates. 可以将上一部分详述的 JSON 架构用在 Azure Resource Manager 模板中,以便在 Azure Resource Manager 模板部署期间运行自定义脚本扩展。The JSON schema detailed in the previous section can be used in an Azure Resource Manager template to run the Custom Script Extension during an Azure Resource Manager template deployment. 若需包含自定义脚本扩展的示例模板,可访问 GitHubA sample template that includes the Custom Script Extension can be found here, GitHub.

{
  "name": "config-app",
  "type": "extensions",
  "location": "[resourceGroup().location]",
  "apiVersion": "2019-03-01",
  "dependsOn": [
    "[concat('Microsoft.Compute/virtualMachines/', concat(variables('vmName'),copyindex()))]"
  ],
  "tags": {
    "displayName": "config-app"
  },
  "properties": {
    "publisher": "Microsoft.Azure.Extensions",
    "type": "CustomScript",
    "typeHandlerVersion": "2.1",
    "autoUpgradeMinorVersion": true,
    "settings": {
        "fileUris": ["https://github.com/MyProject/Archive/hello.sh"]
      },
    "protectedSettings": {
      "commandToExecute": "sh hello.sh <param2>"
    }
  }
}

备注

这些属性名称区分大小写。These property names are case-sensitive. 要避免部署问题,请使用如下所示的名称。To avoid deployment problems, use the names as shown here.

Azure CLIAzure CLI

在使用 Azure CLI 运行自定义脚本扩展时,请创建一个或多个配置文件。When you're using Azure CLI to run the Custom Script Extension, create a configuration file or files. 至少必须具有“commandToExecute”。At a minimum, you must have 'commandToExecute'.

az vm extension set \
  --resource-group myResourceGroup \
  --vm-name myVM --name customScript \
  --publisher Microsoft.Azure.Extensions \
  --protected-settings ./script-config.json

(可选)可以在命令中以 JSON 格式字符串的形式指定设置。Optionally, you can specify the settings in the command as a JSON formatted string. 这样,便可以在执行期间指定配置,而无需使用单独的配置文件。This allows the configuration to be specified during execution and without a separate configuration file.

az vm extension set \
  --resource-group exttest \
  --vm-name exttest \
  --name customScript \
  --publisher Microsoft.Azure.Extensions \
  --settings "{'fileUris': ['https://raw.githubusercontent.com/Microsoft/dotnet-core-sample-templates/master/dotnet-core-music-linux/scripts/config-music.sh']}" \
  --protected-settings "{'commandToExecute': './config-music.sh'}"

Azure CLI 示例Azure CLI examples

包含脚本文件的公共配置Public configuration with script file

{
  "fileUris": ["https://raw.githubusercontent.com/Microsoft/dotnet-core-sample-templates/master/dotnet-core-music-linux/scripts/config-music.sh"],
  "commandToExecute": "./config-music.sh"
}

Azure CLI 命令:Azure CLI command:

az vm extension set \
  --resource-group myResourceGroup \
  --vm-name myVM --name customScript \
  --publisher Microsoft.Azure.Extensions \
  --settings ./script-config.json

不包含脚本文件的公共配置Public configuration with no script file

{
  "commandToExecute": "apt-get -y update && apt-get install -y apache2"
}

Azure CLI 命令:Azure CLI command:

az vm extension set \
  --resource-group myResourceGroup \
  --vm-name myVM --name customScript \
  --publisher Microsoft.Azure.Extensions \
  --settings ./script-config.json

公共和受保护的配置文件Public and protected configuration files

使用公共配置文件来指定脚本文件 URI。You use a public configuration file to specify the script file URI. 使用受保护的配置文件来指定要运行的命令。You use a protected configuration file to specify the command to be run.

公共配置文件:Public configuration file:

{
  "fileUris": ["https://raw.githubusercontent.com/Microsoft/dotnet-core-sample-templates/master/dotnet-core-music-linux/scripts/config-music.sh"]
}

受保护的配置文件:Protected configuration file:

{
  "commandToExecute": "./config-music.sh <param1>"
}

Azure CLI 命令:Azure CLI command:

az vm extension set \
  --resource-group myResourceGroup \
  --vm-name myVM \ 
  --name customScript \
  --publisher Microsoft.Azure.Extensions \
  --settings ./script-config.json \
  --protected-settings ./protected-config.json

故障排除Troubleshooting

运行自定义脚本扩展时,会创建脚本,或将脚本下载到类似于以下示例的目录中。When the Custom Script Extension runs, the script is created or downloaded into a directory that's similar to the following example. 命令输出也会保存到此目录中的 stdoutstderr 文件中。The command output is also saved into this directory in stdout and stderr files.

/var/lib/waagent/custom-script/download/0/

要排除故障,请首先查看 Linux 代理日志,确保扩展运行,并检查:To troubleshoot, first check the Linux Agent Log, ensure the extension ran, check:

/var/log/waagent.log 

应该查找如下所示的扩展执行:You should look for the extension execution, it will look something like:

2018/04/26 17:47:22.110231 INFO [Microsoft.Azure.Extensions.customScript-2.0.6] [Enable] current handler state is: notinstalled
2018/04/26 17:47:22.306407 INFO Event: name=Microsoft.Azure.Extensions.customScript, op=Download, message=Download succeeded, duration=167
2018/04/26 17:47:22.339958 INFO [Microsoft.Azure.Extensions.customScript-2.0.6] Initialize extension directory
2018/04/26 17:47:22.368293 INFO [Microsoft.Azure.Extensions.customScript-2.0.6] Update settings file: 0.settings
2018/04/26 17:47:22.394482 INFO [Microsoft.Azure.Extensions.customScript-2.0.6] Install extension [bin/custom-script-shim install]
2018/04/26 17:47:23.432774 INFO Event: name=Microsoft.Azure.Extensions.customScript, op=Install, message=Launch command succeeded: bin/custom-script-shim install, duration=1007
2018/04/26 17:47:23.476151 INFO [Microsoft.Azure.Extensions.customScript-2.0.6] Enable extension [bin/custom-script-shim enable]
2018/04/26 17:47:24.516444 INFO Event: name=Microsoft.Azure.Extensions.customScript, op=Enable, message=Launch command succeeded: bin/custom-sc

一些需要注意的要点:Some points to note:

  1. Enable 表示该命令何时开始运行。Enable is when the command starts running.
  2. Download 涉及下载 Azure 中的 CustomScript 扩展包,而非 fileUris 中指定的脚本文件。Download relates to the downloading of the CustomScript extension package from Azure, not the script files specified in fileUris.

Azure 脚本扩展生成一个日志,位置如下:The Azure Script Extension produces a log, which you can find here:

/var/log/azure/custom-script/handler.log

应该查找如下所示的个别执行:You should look for the individual execution, it will look something like:

time=2018-04-26T17:47:23Z version=v2.0.6/git@1008306-clean operation=enable seq=0 event=start
time=2018-04-26T17:47:23Z version=v2.0.6/git@1008306-clean operation=enable seq=0 event=pre-check
time=2018-04-26T17:47:23Z version=v2.0.6/git@1008306-clean operation=enable seq=0 event="comparing seqnum" path=mrseq
time=2018-04-26T17:47:23Z version=v2.0.6/git@1008306-clean operation=enable seq=0 event="seqnum saved" path=mrseq
time=2018-04-26T17:47:23Z version=v2.0.6/git@1008306-clean operation=enable seq=0 event="reading configuration"
time=2018-04-26T17:47:23Z version=v2.0.6/git@1008306-clean operation=enable seq=0 event="read configuration"
time=2018-04-26T17:47:23Z version=v2.0.6/git@1008306-clean operation=enable seq=0 event="validating json schema"
time=2018-04-26T17:47:23Z version=v2.0.6/git@1008306-clean operation=enable seq=0 event="json schema valid"
time=2018-04-26T17:47:23Z version=v2.0.6/git@1008306-clean operation=enable seq=0 event="parsing configuration json"
time=2018-04-26T17:47:23Z version=v2.0.6/git@1008306-clean operation=enable seq=0 event="parsed configuration json"
time=2018-04-26T17:47:23Z version=v2.0.6/git@1008306-clean operation=enable seq=0 event="validating configuration logically"
time=2018-04-26T17:47:23Z version=v2.0.6/git@1008306-clean operation=enable seq=0 event="validated configuration"
time=2018-04-26T17:47:23Z version=v2.0.6/git@1008306-clean operation=enable seq=0 event="creating output directory" path=/var/lib/waagent/custom-script/download/0
time=2018-04-26T17:47:23Z version=v2.0.6/git@1008306-clean operation=enable seq=0 event="created output directory"
time=2018-04-26T17:47:23Z version=v2.0.6/git@1008306-clean operation=enable seq=0 files=1
time=2018-04-26T17:47:23Z version=v2.0.6/git@1008306-clean operation=enable seq=0 file=0 event="download start"
time=2018-04-26T17:47:23Z version=v2.0.6/git@1008306-clean operation=enable seq=0 file=0 event="download complete" output=/var/lib/waagent/custom-script/download/0
time=2018-04-26T17:47:23Z version=v2.0.6/git@1008306-clean operation=enable seq=0 event="executing command" output=/var/lib/waagent/custom-script/download/0
time=2018-04-26T17:47:23Z version=v2.0.6/git@1008306-clean operation=enable seq=0 event="executing protected commandToExecute" output=/var/lib/waagent/custom-script/download/0
time=2018-04-26T17:47:23Z version=v2.0.6/git@1008306-clean operation=enable seq=0 event="executed command" output=/var/lib/waagent/custom-script/download/0
time=2018-04-26T17:47:23Z version=v2.0.6/git@1008306-clean operation=enable seq=0 event=enabled
time=2018-04-26T17:47:23Z version=v2.0.6/git@1008306-clean operation=enable seq=0 event=end

可在此处看到:Here you can see:

  • 此日志表示 Enable 命令开始执行The Enable command starting is this log
  • 设置已传递到扩展The settings passed to the extension
  • 扩展下载文件及其结果。The extension downloading file and the result of that.
  • 正在运行的命令及结果。The command being run and the result.

还可以使用 Azure CLI 检索自定义脚本扩展的执行状态,包括作为 commandToExecute 传递的实际参数:You can also retrieve the execution state of the Custom Script Extension including the actual arguments passed as the commandToExecute by using Azure CLI:

az vm extension list -g myResourceGroup --vm-name myVM

输出类似于以下文本:The output looks like the following text:

[
  {
    "autoUpgradeMinorVersion": true,
    "forceUpdateTag": null,
    "id": "/subscriptions/subscriptionid/resourceGroups/rgname/providers/Microsoft.Compute/virtualMachines/vmname/extensions/customscript",
    "resourceGroup": "rgname",
    "settings": {
      "commandToExecute": "sh script.sh > ",
      "fileUris": [
        "https://catalogartifact.azureedge.net/publicartifacts/scripts/script.sh",
        "https://catalogartifact.azureedge.net/publicartifacts/scripts/script.sh"
      ]
    },
    "tags": null,
    "type": "Microsoft.Compute/virtualMachines/extensions",
    "typeHandlerVersion": "2.0",
    "virtualMachineExtensionType": "CustomScript"
  },
  {
    "autoUpgradeMinorVersion": true,
    "forceUpdateTag": null,
    "id": "/subscriptions/subscriptionid/resourceGroups/rgname/providers/Microsoft.Compute/virtualMachines/vmname/extensions/OmsAgentForLinux",
    "instanceView": null,
    "location": "chinaeast",
    "name": "OmsAgentForLinux",
    "protectedSettings": null,
    "provisioningState": "Succeeded",
    "publisher": "Microsoft.EnterpriseCloud.Monitoring",
    "resourceGroup": "rgname",
    "settings": {
      "workspaceId": "workspaceid"
    },
    "tags": null,
    "type": "Microsoft.Compute/virtualMachines/extensions",
    "typeHandlerVersion": "1.0",
    "virtualMachineExtensionType": "OmsAgentForLinux"
  }
]

后续步骤Next steps

若要查看代码、当前问题和版本,请参阅 custom-script-extension-linux 存储库To see the code, current issues and versions, see custom-script-extension-linux repo.