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

重要

此扩展已被弃用,列在此处仅供参考。This extension has been deprecated and is only documented here for informational purposes only. 不建议在部署中继续使用此扩展。We do not recommend you continue to use this extension within your deployments.

自定义脚本扩展版本 1 在 Azure 虚拟机上下载和运行脚本。The Custom Script Extension Version 1 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 门户或 Azure 虚拟机 REST API 来运行它。You can also run it by using Azure CLI, PowerShell, the Azure portal, 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

请切换新部署和现有部署,改用新版本 (Microsoft.Azure.Extensions.CustomScript)。Please switch new and existing deployments to use the new version (Microsoft.Azure.Extensions.CustomScript) 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 分发:Supported Linux Distributions:

  • CentOS 6.5 和更高版本CentOS 6.5 and higher
  • Debian 8 和更高版本Debian 8 and higher
    • Debian 8.7 未在最新映像中随附 Python2,这将中断 CustomScriptForLinux。Debian 8.7 does not ship with Python2 in the latest images, which breaks CustomScriptForLinux.
  • FreeBSDFreeBSD
  • OpenSUSE 13.1 和更高版本OpenSUSE 13.1 and higher
  • SUSE Linux Enterprise Server 11 SP3 和更高版本SUSE Linux Enterprise Server 11 SP3 and higher
  • Ubuntu 12.04 和更高版本Ubuntu 12.04 and higher

脚本位置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.
  • 如果想要计划脚本何时运行,应使用扩展创建一个 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.

扩展架构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": "2015-06-15",
  "dependsOn": [
    "[concat('Microsoft.Compute/virtualMachines/', concat(variables('vmName'),copyindex()))]"
  ],
  "tags": {
    "displayName": "config-app"
  },
  "properties": {
    "publisher": "Microsoft.OSTCExtensions",
    "type": "CustomScriptForLinux",
    "typeHandlerVersion": "1.5",
    "autoUpgradeMinorVersion": true,
    "settings": {
      "fileUris": [
        "<url>"
      ],
      "enableInternalDNSCheck": true
    },
    "protectedSettings": {
      "storageAccountEndPoint": "https://core.chinacloudapi.cn/",
      "storageAccountName": "<storage-account-name>",
      "storageAccountKey": "<storage-account-key>",
      "commandToExecute": "<command>"
    }
  }
}

属性值Property values

名称Name 值/示例Value / Example 数据类型Data Type
apiVersionapiVersion 2015-06-152015-06-15 datedate
publisherpublisher Microsoft.OSTCExtensionsMicrosoft.OSTCExtensions stringstring
typetype CustomScriptForLinuxCustomScriptForLinux stringstring
typeHandlerVersiontypeHandlerVersion 1.51.5 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
enableInternalDNSCheckenableInternalDNSCheck true booleanboolean
storageAccountName(例如)storageAccountName (e.g) examplestorageacctexamplestorageacct 字符串string
storageAccountKey(例如)storageAccountKey (e.g) TmJK/1N3AbAZ3q/+hOXoi/l73zOqsaxXDhqa9Y83/v5UpXQp2DQIBuv2Tifp60cE/OaHsJZmQZ7teQfczQj8hg==TmJK/1N3AbAZ3q/+hOXoi/l73zOqsaxXDhqa9Y83/v5UpXQp2DQIBuv2Tifp60cE/OaHsJZmQZ7teQfczQj8hg== stringstring

属性值详细信息Property value details

  • fileUris:(可选,字符串数组)脚本的 URI 列表fileUris: (optional, string array) the uri list of the scripts
  • enableInternalDNSCheck:(可选,布尔型)默认为 True,设置为 False 可禁用 DNS 检查。enableInternalDNSCheck: (optional, bool) default is True, set to False to disable DNS check.
  • commandToExecute:(可选,字符串)要执行的入口点脚本commandToExecute: (optional, string) the entrypoint script to execute
  • storageAccountName:(可选,字符串)存储帐户的名称storageAccountName: (optional, string) the name of storage account
  • storageAccountKey:(可选,字符串)存储帐户的访问密钥storageAccountKey: (optional, string) the access key of storage account

可以在公共设置或受保护设置中设置以下值,但不得同时在公共设置和受保护设置中设置以下值。The following values can be set in either public or protected settings, you must not have these values below set in both public and protected settings.

  • commandToExecute

虽然使用公共设置可能对调试很有用,但强烈建议使用受保护设置。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.

模板部署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.

{
  "name": "config-app",
  "type": "extensions",
  "location": "[resourceGroup().location]",
  "apiVersion": "2015-06-15",
  "dependsOn": [
    "[concat('Microsoft.Compute/virtualMachines/', concat(variables('vmName'),copyindex()))]"
  ],
  "tags": {
    "displayName": "config-app"
  },
  "properties": {
    "publisher": "Microsoft.OSTCExtensions",
    "type": "CustomScriptForLinux",
    "typeHandlerVersion": "1.5",
    "autoUpgradeMinorVersion": true,
    "settings": {
      "fileUris": ["http://MyAccount.blob.core.chinacloudapi.cn/vhds/MyShellScript.sh"]
    },
    "protectedSettings": {
      "storageAccountEndPoint": "https://core.chinacloudapi.cn/",
      "storageAccountName": "MyAccount",
      "storageAccountKey": "<storage-account-key>",
      "commandToExecute": "sh MyShellScript.sh"
    }
  }
}

备注

这些属性名称区分大小写。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 -n VMAccessForLinux \
  --publisher Microsoft.OSTCExtensions \
  --version 1.5 \
  --vm-name MyVm --resource-group MyResourceGroup \
  --protected-settings '{"commandToExecute": "echo hello"}'

备注

当我们在 Microsoft PowrShell 环境中运行 Azure CLI 时,应在相应的脚本中替换以下格式:When we run the Azure CLI on Microsoft PowrShell environment, we should replace the following format in corresponding script:

  1. \ 的串联替换为 ```。Repalce the concatenation of \ with ```.
  2. protected-settings 的属性替换为实际值。Replace the property of protected-settings with actual value. --protected-settings "{'commandToExecute': 'echo hello'}"

(可选)可以在命令中以 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 CustomScriptForLinux \
  --publisher Microsoft.OSTCExtensions \
  --settings '{"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 examples

不包含脚本文件的公共配置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 CustomScriptForLinux \
  --publisher Microsoft.OSTCExtensions \
  --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 CustomScriptForLinux \
  --publisher Microsoft.OSTCExtensions \
  --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/Microsoft.OSTCExtensions.CustomScriptForLinux-<version>/download/1

要排除故障,请首先查看 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 15:29:44.835067 INFO [Microsoft.OSTCExtensions.CustomScriptForLinux-1.5.2.2] Target handler state: enabled
2018/04/26 15:29:44.867625 INFO [Microsoft.OSTCExtensions.CustomScriptForLinux-1.5.2.2] [Enable] current handler state is: notinstalled
2018/04/26 15:29:44.959605 INFO Event: name=Microsoft.OSTCExtensions.CustomScriptForLinux, op=Download, message=Download succeeded, duration=59
2018/04/26 15:29:44.993269 INFO [Microsoft.OSTCExtensions.CustomScriptForLinux-1.5.2.2] Initialize extension directory
2018/04/26 15:29:45.022972 INFO [Microsoft.OSTCExtensions.CustomScriptForLinux-1.5.2.2] Update settings file: 0.settings
2018/04/26 15:29:45.051763 INFO [Microsoft.OSTCExtensions.CustomScriptForLinux-1.5.2.2] Install extension [customscript.py -install]
2018/04/26 15:29:45 CustomScriptForLinux started to handle.
2018/04/26 15:29:45 [Microsoft.OSTCExtensions.CustomScriptForLinux-1.5.2.2] cwd is /var/lib/waagent/Microsoft.OSTCExtensions.CustomScriptForLinux-1.5.2.2
2018/04/26 15:29:45 [Microsoft.OSTCExtensions.CustomScriptForLinux-1.5.2.2] Change log file to /var/log/azure/Microsoft.OSTCExtensions.CustomScriptForLinux/1.5.2.2/extension.log
2018/04/26 15:29:46.088212 INFO Event: name=Microsoft.OSTCExtensions.CustomScriptForLinux, op=Install, message=Launch command succeeded: customscript.py -install, duration=1005
2018/04/26 15:29:46.133367 INFO [Microsoft.OSTCExtensions.CustomScriptForLinux-1.5.2.2] Enable extension [customscript.py -enable]
2018/04/26 15:29:46 CustomScriptForLinux started to handle.
..
2018/04/26 15:29:47.178163 INFO Event: name=Microsoft.OSTCExtensions.CustomScriptForLinux, op=Enable, message=Launch command succeeded: customscript.py -enable, duration=1012

一些需要注意的要点: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.
  3. 还可查看它写出到 /var/log/azure/Microsoft.OSTCExtensions.CustomScriptForLinux/1.5.2.2/extension.log 的日志文件You can also see which log file it is writing out to /var/log/azure/Microsoft.OSTCExtensions.CustomScriptForLinux/1.5.2.2/extension.log

下一步是查看以下格式的日志文件:Next step is to go an check the log file, this is the format:

/var/log/azure/<extension-name>/<version>/extension.log file.

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

2018/04/26 15:29:46 [Microsoft.OSTCExtensions.CustomScriptForLinux-1.5.2.2] Enable,transitioning,0,Launching the script...
2018/04/26 15:29:46 [Microsoft.OSTCExtensions.CustomScriptForLinux-1.5.2.2] sequence number is 0
2018/04/26 15:29:46 [Microsoft.OSTCExtensions.CustomScriptForLinux-1.5.2.2] setting file path is/var/lib/waagent/Microsoft.OSTCExtensions.CustomScriptForLinux-1.5.2.2/config/0.settings
2018/04/26 15:29:46 [Microsoft.OSTCExtensions.CustomScriptForLinux-1.5.2.2] JSON config: {"runtimeSettings": [{"handlerSettings": {"protectedSettings": "MIIB0AYJKoZIhvcNAQcDoIIBwTCCAb0CAQAxggF+hnEXRtFKTTuKiFC8gTfHKupUSs7qI0zFYRya", "publicSettings": {"fileUris": ["https://dannytesting.blob.core.chinacloudapi.cn/demo/myBash.sh"]}, "protectedSettingsCertThumbprint": "4385AB21617C2452FF6998C0A37F71A0A01C8368"}}]}
2018/04/26 15:29:46 [Microsoft.OSTCExtensions.CustomScriptForLinux-1.5.2.2] Config decoded correctly.
2018/04/26 15:29:46 [Microsoft.OSTCExtensions.CustomScriptForLinux-1.5.2.2] Will try to download files, number of retries = 10, wait SECONDS between retrievals = 20s
2018/04/26 15:29:46 [Microsoft.OSTCExtensions.CustomScriptForLinux-1.5.2.2] Downloading,transitioning,0,Downloading files...
2018/04/26 15:29:46 [Microsoft.OSTCExtensions.CustomScriptForLinux-1.5.2.2] No azure storage account and key specified in protected settings. Downloading scripts from external links...
2018/04/26 15:29:46 [Microsoft.OSTCExtensions.CustomScriptForLinux-1.5.2.2] Converting /var/lib/waagent/Microsoft.OSTCExtensions.CustomScriptForLinux-1.5.2.2/download/0/myBash.sh from DOS to Unix formats: Done
2018/04/26 15:29:46 [Microsoft.OSTCExtensions.CustomScriptForLinux-1.5.2.2] Removing BOM of /var/lib/waagent/Microsoft.OSTCExtensions.CustomScriptForLinux-1.5.2.2/download/0/myBash.sh: Done
2018/04/26 15:29:46 [Microsoft.OSTCExtensions.CustomScriptForLinux-1.5.2.2] Succeeded to download files, retry count = 0
2018/04/26 15:29:46 [Microsoft.OSTCExtensions.CustomScriptForLinux-1.5.2.2] Internal DNS is ready, retry count = 0
2018/04/26 15:29:47 [Microsoft.OSTCExtensions.CustomScriptForLinux-1.5.2.2] Command is finished.
2018/04/26 15:29:47 ---stdout---
2018/04/26 15:29:47
2018/04/26 15:29:47 ---errout---
2018/04/26 15:29:47
2018/04/26 15:29:47
2018/04/26 15:29:47 [Microsoft.OSTCExtensions.CustomScriptForLinux-1.5.2.2] Daemon,success,0,Command is finished.
2018/04/26 15:29:47 ---stdout---
2018/04/26 15:29:47
2018/04/26 15:29:47 ---errout---
2018/04/26 15:29:47
2018/04/26 15:29:47

可在此处看到: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 来检索自定义脚本扩展的执行状态:You can also retrieve the execution state of the Custom Script Extension by using Azure CLI:

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

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

Name                  ProvisioningState    Publisher                   Version  AutoUpgradeMinorVersion
--------------------  -------------------  ------------------------  ---------  -------------------------
CustomScriptForLinux  Succeeded            Microsoft.OSTCExtensions        1.5  True

后续步骤Next steps

若要查看代码、当前问题和版本,请参阅 CustomScript 扩展存储库To see the code, current issues and versions, see CustomScript Extension repo.