文档

使用实例自定义数据在实例启动时自动执行命令或脚本

更新时间:

实例自定义数据是指用户上传给实例的脚本、指令或配置文件等数据,可用来完成实例初始化或其他配置,例如实例首次启动时,自动运行服务启动脚本、安装软件、打印日志等。本文介绍如何将自定义数据传入ECS实例、修改自定义数据、如何查看自定义数据等。

实例首次启动时会自动运行自定义数据,部分自定义数据格式还支持在Linux实例每次启动时都运行。详细说明,请参见自定义数据格式及运行频率

使用限制

  • 实例的网络类型必须为专有网络VPC。

  • 实例必须使用公共镜像或基于公共镜像创建的自定义镜像,且操作系统需为以下类型之一:

    • Alibaba Cloud Linux、CentOS、CentOS Stream、Ubuntu、SUSE Linux Enterprise Server、Red Hat Enterprise Linux、OpenSUSE、Debian、AlmaLinux、Rocky Linux、Fedora

    • Windows Server 2008 R2及更高版本

  • 已停售的实例规格中,仅I/O优化实例支持实例自定义数据功能,非I/O优化实例不支持该功能。更多信息,请参见已停售的实例规格

使用自定义数据

将自定义数据传入ECS实例

  1. 准备实例自定义数据。

    支持的自定义数据格式、任务被执行频率及其说明,请参见自定义数据格式及运行频率

    重要

    自定义数据内容可不经过Base64编码,且在未经过Base64编码前的大小不能超过32 KB。

  2. 将自定义数据传入ECS实例。

    • 创建新实例时传入:数据会在实例首次启动时、更换操作系统、重新初始化系统盘时被执行。

    • 修改已有实例的自定义数据:数据会在实例更换操作系统、重新初始化系统盘时被执行。

      部分自定义数据格式还支持在Linux实例每次重启时被执行。详细说明,请参见自定义数据格式及运行频率

  3. 创建新实例时传入自定义数据

    实例购买页展开高级选项区域,在自定义数据区域输入实例自定义数据。

    如果实例自定义数据已进行Base64编码,请勾选输入已采用Base64编码,且在进行Base64编码前自定义数据内容的大小不能超过32 KB。否则,无需勾选,系统会自动对内容进行Base64编码。

    修改已有实例的自定义数据

    1. 确保实例处于已停止状态。

      重要

      如果实例的计费方式为按量付费、网络类型为专有网络,停止实例时,停止模式建议选择普通停机模式,选择节省停机模式会因计算资源(vCPU和内存)被回收,再次启动实例时可能因为库存不足导致启动失败。更多信息,请参见节省停机模式

    2. 实例页面,选择icon1 > 实例设置 > 设置用户数据,然后在用户数据区域输入自定义数据。

  4. 根据设置的脚本内容验证自定义数据的运行效果。

    说明

    当User-Data执行遇到问题时,可以通过云助手公共命令ACS-ECS-UserData-Check-for-linux.sh来获取失败相关的错误日志。如果返回有错误信息表示脚本执行有问题,如果没有返回错误信息表示执行没有报错,需要排查其他方面。关于云助手公共命令的更多信息,请参见查看和执行公共命令

    例如我们在Linux实例中传入了User-Data脚本,内容如下:

    #!/bin/sh
    echo "Hello World. The time is now $(date -R)!" | tee /root/userdata_test.txt

    您可以运行cat userdata_test.txt命令来查看效果,系统已经向userdata_test.txt文件写入系统时间。

    view-result

查看实例的自定义数据

自定义数据传入实例后,您可以通过元数据或控制台查看实例的自定义数据信息。

通过元数据获取(普通模式)

  • Linux实例

    curl http://100.100.100.200/latest/user-data
  • Windows实例

    Invoke-RestMethod http://100.100.100.200/latest/user-data

通过元数据获取(加固模式)

假设,设置元数据服务器访问凭证有效期为180秒。

  • Linux实例

    TOKEN=`curl -X PUT "http://100.100.100.200/latest/api/token" -H "X-aliyun-ecs-metadata-token-ttl-seconds:180"`
    curl -H "X-aliyun-ecs-metadata-token: $TOKEN" http://100.100.100.200/latest/user-data
  • Windows实例

    $token = Invoke-RestMethod -Headers @{"X-aliyun-ecs-metadata-token-ttl-seconds" = "180"} -Method PUT –Uri http://100.100.100.200/latest/api/token
    Invoke-RestMethod -Headers @{"X-aliyun-ecs-metadata-token" = $token} -Method GET -Uri http://100.100.100.200/latest/user-data

通过控制台获取

  1. 确保实例处于已停止状态。

    重要

    如果实例的计费方式为按量付费、网络类型为专有网络,停止实例时,停止模式建议选择普通停机模式,选择节省停机模式会因计算资源(vCPU和内存)被回收,再次启动实例时可能因为库存不足导致启动失败。更多信息,请参见节省停机模式

  2. 实例页面,选择icon1 > 实例设置 > 设置用户数据,然后在用户数据区域查看已设置的自定义数据。

关于元数据的更多说明,请参见实例元数据

Linux脚本使用示例

示例一:使用User-Data脚本自定义yum源、NTP服务和DNS服务

系统会在实例启动时自动配置默认的yum源、NTP服务和DNS服务,您可以使用实例自定义数据更改默认的yum源、NTP服务和DNS服务,但请注意:

  • 如果您自定义了yum源,阿里云官方不再提供yum源相关支持。

  • 如果您自定义了NTP服务,阿里云官方不再提供相关时间同步服务。

适用于CentOS 7.2的示例User-Data脚本如下:

#!/bin/sh
# Modify DNS
echo "nameserve 8.8.X.X" | tee /etc/resolv.conf
# Modify yum repo and update
rm -rf /etc/yum.repos.d/*
touch myrepo.repo
echo "[base]" | tee /etc/yum.repos.d/myrepo.repo
echo "name=myrepo" | tee -a /etc/yum.repos.d/myrepo.repo
echo "baseurl=https://mirror.centos.org/centos" | tee -a /etc/yum.repos.d/myrepo.repo
echo "gpgcheck=0" | tee -a /etc/yum.repos.d/myrepo.repo
echo "enabled=1" | tee -a /etc/yum.repos.d/myrepo.repo
yum update -y
# Modify NTP Server
echo "server ntp1.aliyun.com" | tee /etc/ntp.conf
systemctl restart ntpd.service
说明
  • 其中8.8.X.X为DNS服务器地址、https://mirror.centos.org/centos为CentOS的yum仓库地址、server ntp1.aliyun.com为阿里云的NTP服务器地址,请您根据实际环境替换。

  • 您也可以使用Cloud Config数据更改yum源,但是不够灵活,不能适配阿里云已对部分yum源进行预配置的情况,建议使用User-Data脚本。

在创建实例时设置实例自定义数据,启动后登录实例查看效果,确认实例的yum源、NTP服务和DNS服务配置符合预期,如下所示。

[root@iZbp1csxtw7jo9zp12s**** ~]# cat /etc/yum.repos.d/myrepo.repo
[base]
name=myrepo
baseurl=https://mirror.centos.org/centos
gpgcheck=0
enabled=1
[root@iZbp1csxtw7jo9zp12s**** ~]# cat /etc/resolv.conf
nameserver 8.8.X.X
[root@iZbp1csxtw7jo9zp12s**** ~]# ping www.baidu.com
PING www.a.shifen.com (14.215.XX.XX) 56(84) bytes of data.
64 bytes from 14.215.XX.XX (14.215.XX.XX): icmp_seq=1 ttl=52 time=26.3 ms
64 bytes from 14.215.XX.XX (14.215.XX.XX): icmp_seq=2 ttl=52 time=26.3 ms
64 bytes from 14.215.XX.XX (14.215.XX.XX): icmp_seq=3 ttl=52 time=26.2 ms
^Z
[2]+  Stopped                 ping www.baidu.com
[root@iZbp1csxtw7jo9zp12s**** ~]# cat /etc/ntp.conf
server ntp1.aliyun.com
[root@iZbp1csxtw7jo9zp12s**** ~]# systemctl status ntpd.service
● ntpd.service - Network Time Service
   Loaded: loaded (/usr/lib/systemd/system/ntpd.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2021-09-06 14:53:19 CST; 13min ago
 Main PID: 5795 (ntpd)
   CGroup: /system.slice/ntpd.service
           └─5795 /usr/sbin/ntpd -u ntp:ntp -g

Sep 06 14:53:19 iZbp1cjdaurreftzgpgvqoZ ntpd[5795]: Listen and drop on 1 v6wildcard :: UDP 123
Sep 06 14:53:19 iZbp1cjdaurreftzgpgvqoZ ntpd[5795]: Listen normally on 2 lo 127.0.XX.XX UDP 123
Sep 06 14:53:19 iZbp1cjdaurreftzgpgvqoZ ntpd[5795]: Listen normally on 3 eth0 192.168.XX.XX UDP 123
Sep 06 14:53:19 iZbp1cjdaurreftzgpgvqoZ ntpd[5795]: Listening on routing socket on fd #20 for interface updates
Sep 06 14:53:19 iZbp1cjdaurreftzgpgvqoZ ntpd[5795]: 0.0.XX.XX c016 06 restart
Sep 06 14:53:19 iZbp1cjdaurreftzgpgvqoZ ntpd[5795]: 0.0.XX.XX c012 02 freq_set kernel 0.000 PPM
Sep 06 14:53:19 iZbp1cjdaurreftzgpgvqoZ ntpd[5795]: 0.0.XX.XX c011 01 freq_not_set
Sep 06 14:56:34 iZbp1cjdaurreftzgpgvqoZ ntpd[5795]: 0.0.XX.XX c61c 0c clock_step +0.464773 s
Sep 06 14:56:35 iZbp1cjdaurreftzgpgvqoZ ntpd[5795]: 0.0.XX.XX c614 04 freq_mode
Sep 06 14:56:36 iZbp1cjdaurreftzgpgvqoZ ntpd[5795]: 0.0.XX.XX c618 08 no_sys_peer

示例二:使用User-Data脚本自定义管理员账号

Linux实例默认使用root用户作为管理员,您可以使用实例自定义数据使用其他用户作为管理员。

适用于CentOS 7.2的示例User-Data脚本如下:

#!/bin/sh
useradd test
echo "test   ALL=(ALL)        NOPASSWD:ALL" | tee -a /etc/sudoers
mkdir /home/test/.ssh
touch /home/test/.ssh/authorized_keys
echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCRnnUveAis****" | tee -a /home/test/.ssh/authorized_keys
说明

请使用您的公钥替换示例中的公钥ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCRnnUveAis****

示例User-Data脚本的效果如下:

  • 创建名为test的用户,并将其作为管理员账号使用。

  • 仅允许该用户使用SSH密钥对远程连接实例,不能使用用户密码。

  • 如果该用户执行需要管理员权限的操作,通过sudo命令提权即可,无需输入密码。

在创建实例时设置实例自定义数据,启动后可以通过test用户和SSH密钥对远程连接实例,如果尝试使用密码登录会报错。连接实例后,可以通过sudo命令提权执行需要管理员权限的操作,示例如下。

[test@iZbp1csxtw7jo9zp12s**** ~]$ cd /root
-bash: cd: /root: Permission denied
[test@iZbp1csxtw7jo9zp12s**** ~]$ sudo cd /root
[test@iZbp1csxtw7jo9zp12s**** ~]$ 

自定义数据格式及运行频率

Linux实例

Linux实例是通过cloud-init组件控制实例的启动行为。在实例首次启动过程中,系统会自动运行自定义数据。实例重启时,自定义数据是否会被执行,由自定义数据的格式决定。

如何判定Linux实例是否是首次启动

实例启动、更换操作系统、重新初始化系统盘时,cloud-init会判断当前系统上是否存在缓存目录,且缓存是否指向了当前实例的实例ID。如果一致,则表示系统是首次启动,否则表示系统不是首次启动。具体详情请参见Boot stages

常见的几种Linux实例自定义数据格式如下:

说明
  • 自定义数据格式的详细说明,可参见cloud-init文档User-Data Formats

  • 如果您的User-Data脚本、Cloud Config数据或Include文件内容的大小超过32 KB,数据类型建议选择Gzip压缩内容

  • 如果任务需要在实例每次启动时都执行,数据类型建议选择Cloud Config数据Upstart Job

User-Data脚本

  • 简介

    User-Data脚本传入Linux实例后直接作为Shell脚本执行,且仅在实例首次启动时运行一次。

  • 运行频率

    • 启动实例:仅在实例首次启动时运行一次,重启实例不会再自动运行。

    • 更换操作系统:自动运行。

    • 重新初始化系统盘:自动运行。

    重要

    以下情况不会自动运行脚本:

    • 如果更换操作系统使用的是自定义镜像且来源于原实例,更换操作系统时会判断实例不是初次启动,因此不会自动运行脚本。

    • 如果创建使用的是自定义镜像,则创建实例时系统盘就有数据,初始化系统盘时会判断实例不是初次启动,因此不会自动运行脚本。

  • 格式

    首行均以#!开头。

  • User-Data脚本示例

    #!/bin/sh
    echo "Hello World. The time is now $(date -R)!" | tee /root/userdata_test.txt

    示例User-Data脚本的效果是在实例首次启动时,向userdata_test.txt文件写入系统时间。

Cloud Config数据

  • 简介

    在Cloud-init中,定义了一系列的功能模块,来完成部分需要执行的任务和配置,例如安装软件包、设置网络等。执行哪些模块及具体的执行逻辑,由Cloud Config数据决定,可从vendordata、自定义数据、内核参数中获取。在创建ECS实例时,用户可自定义Cloud Config数据,指定需要执行的模块和任务,并作为自定义数据提供给实例。实例启动时,cloud-init会读取并解析Cloud Config数据,并按照配置文件中的指示运行对应模块并执行配置任务,自动配置和部署ECS实例。

  • 运行频率

    • 启动实例:Cloud Config数据中的任务是否会被执行,取决于这些任务对应模块的频率设置。各模块的说明,请参见Modules

      • 频率为once-per-instance:仅在实例首次启动时运行。例如配置的是Apt、Set Passwords等模块,运行频率为once-per-instance,重启实例时不会运行。

      • 频率为always:实例每次启动都运行。例如配置的是Bootcmd、Update Etc Hosts等模块,运行频率为always,实例每次启动都运行。

    • 更换操作系统:自动运行。

    • 重新初始化系统盘:自动运行。

      重要

      以下情况不会自动运行脚本:

      • 如果更换操作系统使用的是自定义镜像且来源于原实例,更换操作系统时会判断实例不是初次启动,因此不会自动运行脚本。

      • 如果创建使用的是自定义镜像,则创建实例时系统盘就有数据,初始化系统盘时会判断实例不是初次启动,因此不会自动运行脚本。

  • 格式

    • 首行为#cloud-config,且起始位置不能有空格。

    • 必须遵循YAML语法编写内容。

  • Cloud Config数据示例

    #cloud-config
    apt:
     primary:
     - arches: [default]
     uri: https://us.archive.ubuntu.com/ubuntu/
    bootcmd:
    - echo "Hello World. The time is now $(date -R)!" | tee /root/userdata_test.txt

    示例Cloud Config数据的效果是修改默认的软件源,并在实例每次启动时向userdata_test.txt文件写入最新的系统时间。

Include文件

  • 简介

    通过Include文件指向一个或多个User-Data脚本或Cloud Config数据的链接,多个链接按行分隔。实例启动时,cloud-init会逐个解析并读取链接里的内容。如果在读取某一个链接的内容时出错,则停止读取剩余的链接。

    说明

    您可以通过阿里云对象存储OSS,上传User-Data脚本或Cloud Config数据、获取链接、设置链接有效期等。具体操作,请参见OSS控制台快速入门

  • 运行频率

    • 启动实例:执行频率由链接里的内容决定。例如,链接的内容为User-Data脚本,则仅在实例首次启动时运行一次;脚本类型链接的内容为Cloud Config数据,则遵循Cloud Config数据的运行频率。

    • 更换操作系统:自动运行。

    • 重新初始化系统盘:自动运行。

      重要

      以下情况不会自动运行脚本:

      • 如果更换操作系统使用的是自定义镜像且来源于原实例,更换操作系统时会判断实例不是初次启动,因此不会自动运行脚本。

      • 如果创建使用的是自定义镜像,则创建实例时系统盘就有数据,初始化系统盘时会判断实例不是初次启动,因此不会自动运行脚本。

  • 格式

    首行为#include,且起始位置不能有空格。

  • Include文件示例

    #include
    https://ecs-image-test.oss-cn-hangzhou.aliyuncs.com/userdata/myscript.sh

    示例Include文件包含一个脚本链接,该脚本为User-Data脚本,则仅在实例首次启动时运行一次。

    说明

    如果您采用Include文件或Gzip压缩内容的方式,需要使用存储服务上传脚本、获取脚本链接、设置链接有效期等操作,推荐您使用阿里云对象存储OSS。具体操作,请参见OSS控制台快速入门

Gzip压缩内容

  • 简介

    如果您的User-Data脚本、Cloud Config数据或Include文件内容的大小超过32 KB,可以采用Gzip压缩内容(.gz格式)并做成链接,然后以Include文件的形式输入。cloud-init会自动解压Gzip压缩内容,运行解压后内容的效果和直接传入后运行没有区别。

    说明

    您可以通过阿里云对象存储OSS,上传User-Data脚本或Cloud Config数据、获取链接、设置链接有效期等。具体操作,请参见OSS控制台快速入门

  • 运行频率

    • 启动实例:由脚本类型和模块类型决定。例如,Gzip压缩内容链接的脚本类型为User-Data脚本,则仅在实例首次启动时运行一次。

    • 更换操作系统:自动运行。

    • 重新初始化系统盘:自动运行。

      重要

      以下情况不会自动运行脚本:

      • 如果更换操作系统使用的是自定义镜像且来源于原实例,更换操作系统时会判断实例不是初次启动,因此不会自动运行脚本。

      • 如果创建使用的是自定义镜像,则创建实例时系统盘就有数据,初始化系统盘时会判断实例不是初次启动,因此不会自动运行脚本。

  • 格式

    首行为#include,且起始位置不能有空格。

  • Gzip压缩内容示例

    #include
    https://ecs-image-test.oss-cn-hangzhou.aliyuncs.com/userdata/myscript.gz

    示例Gzip压缩内容表示Include文件包含一个Gzip压缩内容链接,cloud-init读取该Gzip压缩内容后会自动解压并运行,该Gzip压缩内容由User-Data脚本压缩得到,所以仅在实例首次启动时运行一次。

Upstart Job

说明

如需使用Upstart Job,您需要为实例安装upstart服务,支持采用upstart服务管理启动行为的操作系统有CentOS 6、Ubuntu 10/12/14以及Debian 6/7。

  • 简介

    Upstart是一个事件驱动型的初始化系统,Upstart Job是一个配置文件,定义了一个服务或任务何时启动、停止和如何运行。它通常放置在/etc/init/目录下,文件扩展名为.conf。

  • 运行频率

    • 启动实例:实例每次启动都会自动运行。

    • 更换操作系统:自动运行。

    • 重新初始化系统盘:自动运行。

      重要

      以下情况不会自动运行脚本:

      • 如果更换操作系统使用的是自定义镜像且来源于原实例,更换操作系统时会判断实例不是初次启动,因此不会自动运行脚本。

      • 如果创建使用的是自定义镜像,则创建实例时系统盘就有数据,初始化系统盘时会判断实例不是初次启动,因此不会自动运行脚本。

  • 格式

    首行为#upstart-job,且起始位置不能有空格。

  • Upstart Job内容示例

    #upstart-job
    description "upstart test"
    start on runlevel [2345] #在运行级别2、3、4、5执行
    stop on runlevel [!2345] #在运行级别2、3、4、5以外不执行
    exec echo "Hello World. The time is now $(date -R)!" | tee /root/output.txt

    示例Upstart Job表示在系统进入指定的运行级别时输出一条包含时间戳的消息,并将该消息记录到/root/output.txt文件中。当系统离开这些运行级别时,作业会停止执行。

Windows实例

Windows实例是通过Vminit组件的Plugin_Main_CloudinitUserData组件来运行自定义数据脚本,该插件仅支持在实例首次启动时运行。更多信息,请参见Vminit组件说明

Windows自定义数据脚本支持Bat和PowerShell两种类型。

Bat脚本

  • 运行频率

    • 启动实例:实例首次启动时运行一次,重启实例不会自动运行。

    • 更换操作系统:自动运行。

    • 重新初始化系统盘:自动运行。

      重要

      以下情况不会自动运行脚本:

      • 如果更换操作系统使用的是自定义镜像且来源于原实例,更换操作系统时会判断实例不是初次启动,因此不会自动运行脚本。

      • 如果创建使用的是自定义镜像,则创建实例时系统盘就有数据,初始化系统盘时会判断实例不是初次启动,因此不会自动运行脚本。

  • 格式

    • 首行为[bat],且起始位置不能有空格。

    • 只能输入半角字符,不能有多余字符。

    • 写入数据的路径不能为C:\Users目录,否则自定义数据会执行失败。

      说明

      在Windows系统中,C:\Users及其子目录是用户配置文件和数据的默认存储位置,需要登录系统后才可以访问,而在系统初始化执行userdata阶段实际还未登录系统,所以写入数据到C:\Users目录会失败。

  • Bat脚本示例

    [bat]
    echo "bat test" > C:\userdata_test.txt

    示例Bat脚本的效果是在实例首次启动时向userdata_test.txt文件写入内容"bat test"

PowerShell脚本

  • 运行频率

    • 启动实例:实例首次启动时运行一次,重启实例不会自动运行。

    • 更换操作系统:自动运行。

    • 重新初始化系统盘:自动运行。

      重要

      以下情况不会自动运行脚本:

      • 如果更换操作系统使用的是自定义镜像且来源于原实例,更换操作系统时会判断实例不是初次启动,因此不会自动运行脚本。

      • 如果创建使用的是自定义镜像,则创建实例时系统盘就有数据,初始化系统盘时会判断实例不是初次启动,因此不会自动运行脚本。

  • 格式

    • 首行为[powershell],且起始位置不能有空格。

    • 只能输入半角字符,不能有多余字符。

    • 写入数据的路径不能为C:\Users目录,否则自定义数据会执行失败。

      说明

      在Windows系统中,C:\Users及其子目录是用户配置文件和数据的默认存储位置,需要登录系统后才可以访问,而在系统初始化执行userdata阶段实际还未登录系统,所以写入数据到C:\Users目录会失败。

  • PowerShell脚本示例

    [powershell]
    write-output "powershell test" | Out-File C:\userdata_test.txt

    示例PowerShell脚本的效果是在实例首次启动时向userdata_test.txt文件写入内容powershell test

相关文档

  • 您可以调用DescribeUserData接口查询一台ECS实例的自定义数据。

  • 您也可以通过弹性伸缩的自定义数据功能,让多台ECS实例在启动时自动执行配置的脚本或命令,确保ECS实例配置的一致性,简化了运维工作。更多信息,请参见使用实例自定义数据自动配置ECS实例

  • 如果希望服务或脚本因程序异常、服务器重启、掉电等被中断时,及时恢复运行,云助手插件ecs-tool-servicekeepalive实现。具体操作,请参见自动恢复服务