摘要
是的,你没有看错!云助手RunCommand API发布,执行云助手命令从需要先创建命令(CreateCommand)再执行命令(InvokeCommand)的“二点灵”时代,进入了只需一次RunCommand的“一点灵”时代。
背景
用户在使用云助手的时候,经常会遇到以下场景。
场景一
用户:我要通过云助手去部署环境,命令无法复用,必须每次都要创建一个新的命令么?
我:是的。需要先创建一条云助手命令,再执行这条云助手命令。
用户:这么麻烦。。。
场景二
用户:我通过OpenAPI调用云助手,执行结果为乱码,为什么???
我:请确认输入的命令是否经过Base64编码,如果没有经过Base64编码的命令内容,云助手无法解析哦。
用户:不支持直接明文传递命令内容吗?
我:暂时不支持。
用户:。。。
场景三
用户:我的命令数量超过了quota,无法创建新的命令,影响了我的线上服务,怎么办???
我:亲,这边建议把不用的命令清理一下哦。
用户:???
这些场景给用户使用云助手带来了极大的不便和困扰,RunCommand的引入将有效缓解以上问题。
功能介绍
行云流水的执行流程
统计发现,超过80%的云助手命令在创建后只执行了一次,所以先创建命令、再去执行命令的方式,不仅使云助手的执行流程异常繁琐,也极大的提高了用户管理云助手命令的成本。
通过调用RunCommand,用户传入必要信息,如命令内容、目标实例ID等,即可创建并执行一条命令。当命令执行完毕、手动停止或执行失败后,命令会被自动清除,不占用用户创建命令的quota。RunCommand淡化“命令”,强调“执行”,每次RunCommand即是一次执行,可以通过DescribeInvocations和DescribeInvocationResults返回执行的结果。用户不需要关心“命令”的概念,命令执行完成后即被删除,通过DescribeCommands查询也不会返回该命令。我们希望用户能够更加简单的执行云助手命令,下图显示了云助手执行命令流程的变化:两步并为一步,而且不必担心创建命令超过限额。
“一招鲜”的通用接口
RunCommand的定位,是提供一个全新的接口,覆盖掉原有逻辑中不合理的部分,所以RunCommand完全覆盖了CreateCommand的全部功能,包括命令支持自定义参数等。也就是说,今后可以用RunCommand完全代替CreateCommand去创建和执行命令。如果在执行RunCommand时,指定KeepCommand参数为true,则会在此次执行之后仍然保留命令。后续仍可以通过命令ID去执行该命令,行为上完全与CreateCommand创建的命令相同。
DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "<accessKeyId>", "<accessSecret>");
IAcsClient client = new DefaultAcsClient(profile);
RunCommandRequest request = new RunCommandRequest();
request.setCommandContent("echo hello");
request.setType("RunShellScript");
request.setName("test_runcommand");
List<String> instanceIdList = new ArrayList<String>();
instanceIdList.add("i-XXXX");
request.setInstanceIds(instanceIdList);
//在执行完成后保留命令
request.setKeepCommand(true);
try {
RunCommandResponse response = client.getAcsResponse(request);
System.out.println(new Gson().toJson(response));
} catch (ServerException e) {
e.printStackTrace();
} catch (ClientException e) {
System.out.println("ErrCode:" + e.getErrCode());
System.out.println("ErrMsg:" + e.getErrMsg());
System.out.println("RequestId:" + e.getRequestId());
}
返回结果
{
"requestId":"B66550CC-XXXX-XXXX-XXXX-4A7195695CD2",
"commandId":"c-XXXXXXXXXXX",
"invokeId":"t-XXXXXXXXX"
}
通过该commandId,可以再次执行该命令,该命令会占用创建命令的quota。
所见即所得的命令内容
原有接口无论在创建还是查询时,命令内容都以Base64编码的形式呈现。云助手控制台屏蔽了这个问题,用户看到的依然是明文形式的命令。但对于阿里云CLI用户来讲,进行Base64转码是件非常麻烦的事情,可能需要自己去写代码或借助于第三方工具。创建命令的例子如下,CommandContent字段是一段长长的Base64编码,非常不直观。
aliyun ecs CreateCommand --RegionId cn-hangzhou --CommandContent ZWNobyBoZWxsbyB3b3JsZAplY2hvIGhlbGxvIFJ1bkNvbW1hbmQ= --Type RunShellScript --Name testCLI
RunCommand提供所见即所得的API,默认用户传入明文形式的命令内容,换行符用“n”表示。通过RunCommand,阿里云CLI用户可以更方便的创建命令(需要使用CLI 3.0.27以上版本)。当然,用户仍能传入Base64形式的命令内容,只需要指定ContentEncoding字段为“Base64”即可。
aliyun ecs RunCommand --RegionId cn-hangzhou --CommandContent 'echo hello world\necho hello RunCommand' --Type RunShellScript --Name testCLI --InstanceId.1 i-XXXXXX
...
执行结果
hello world
hello RunCommand
对于查询接口DescribeCommands和DescribeInvocations,为了保持兼容,返回的命令内容默认仍为Base64编码形式,但可以通过指定ContentEncoding为“PlainText”来返回明文。
//查询上面的执行记录
DescribeInvocationsRequest request = new DescribeInvocationsRequest();
request.setContentEncoding("PlainText");
...
返回结果的命令内容字段
"echo hello world;\necho hello RunCommand"
控制台使用
RunCommand对控制台的改动很小,入口仍为“创建命令”按钮,在填入命令信息后,点击“立即执行”就可以进入执行信息配置页面。
选择目标执行实例,即可开始执行,同样支持单次执行和周期执行。如果选择“保留命令”,则命令会在执行完成之后被保留,并能够再次执行;否则执行完成后自动清理掉命令,节约命令管理空间。
相关API
以上功能对云助手API产生了如下变化。
RunCommand
增加了RunCommand API。
- RunCommand请求参数
名称 | 类型 | 是否必选 | 示例值 | 描述 |
---|---|---|---|---|
CommandContent | String | 是 | echo hello | 命令内容,默认采用明文方式传输。 脚本内容的大小不能超过 16 KB。 |
EnableParameter | Boolean | 否 | false | 创建的命令是否携带自定义参数。 默认值:false,表示不在命令中携带自定义参数。 |
Type | String | 是 | RunShellScript | 命令的类型。取值范围: BatScript:创建一个在 Windows 实例中运行的 Bat 脚本。 PowerShellScript:创建一个在 Windows 实例中运行的 PowerShell 脚本。 * ShellScript:创建一个在 Linux 实例中运行的 Shell 脚本。 |
Description | String | 否 | Test1 | 命令描述,支持全字符集。 长度不得超过512个字符。 |
Timeout | Long | 否 | 3600 | 命令在 ECS 实例中执行时最大的超时时间,单位为秒。 默认值:3600。 |
WorkingDir | String | 否 | /home | 命令在 ECS 实例中运行的目录。默认值: 对于 Linux 实例,默认在管理员 root 用户的 home 目录下,具体为 /root 目录。 对于 Windows 实例,默认在云助手客户端进程所在目录,例如,C:ProgramDataaliyunassist$(version)。 |
InstanceId.N | RepeatList | 是 | i-bp185dy2o3o6nxxxxxxx | 需要执行命令的实例列表,最多能指定 50 台实例 ID。 N 的取值范围为1~50。 |
Timed | Boolean | 否 | true | 命令是否为周期执行。 默认值:False。 |
Frequency | String | 否 | 0 /20 * | 周期任务的执行周期,两次周期任务的时间间隔不能低于10秒。 当参数 Timed 的值为 True 时,参数 Frequency 为必需参数。 |
Parameters | Json | 否 | {"name":"Jack", "accessKey":"LTAIdyvaRY"} | 启用自定义参数功能时,执行命令时传入的自定义参数的键值对。 |
KeepCommand | Boolean | 否 | true | 执行完毕该命令后,是否保留该命令。 默认值为false,即在每次执行后自动删除命令; 如选择保留命令,则该命令会像普通命令一样,可以通过InvokeCommand再次执行,通过DescribeCommands查询,并通过DeleteCommands删除,并会占用用户创建命令的限额。 |
ContentEncoding | String | 否 | base64 | CommandContent的编码方式,默认为PlainText,表示明文传输。 取值范围(不区分大小写): PlainText:明文传输; Base64:传入Base64编码的CommandContent其余值均按照明文处理。 |
- RunCommand返回参数
名称 | 类型 | 示例值 | 描述 |
---|---|---|---|
CommandId | String | c-7d2a745b412b4601b2d47f6a768dXXXX | 命令 ID。 当KeepCommand为false时,该CommandId不能被再次执行, 命令也不能通过DescribeCommands接口查询。 |
InvokeId | String | t-7d2a745b412b4601b2d47f6a768dXXXX | 命令执行ID |
RequestId | String | 473469C7-AA6F-4DC5-B3DB-A3DC0DE3XXXX | 请求 ID |
DescribeCommands
通过RunCommand创建的命令,如果指定了KeepCommand为false,则不能通过DescribeCommands返回,如果希望查看执行情况,可以通过DescribeInvocations和DescribeInvocationResults查询。如果指定了KeepCommand为true,则与通过CreateCommand创建的命令相同。
由于RunCommand的命令可以采取多种编码方式,所以DescribeCommands的返回值也应该支持多种编码方式。为保证兼容性,默认的返回值仍为Base64编码,请求参数中加入ContentEncoding字段允许用户选择其他编码方式。
名称 | 类型 | 是否必选 | 示例值 | 描述 |
---|---|---|---|---|
ContentEncoding | String | 否 | Base64 | 返回的CommandContent的编码方式,默认为Base64。取值范围(不区分大小写): PlainText:返回明文形式的CommandContent Base64:返回Base64编码的CommandContent其余值均按照Base64处理 |
DescribeInvocations
DescribeInvocations也会返回CommandContent信息,与DescribeCommands类似,请求参数中加入ContentEncoding字段允许用户选择其他编码方式。
名称 | 类型 | 是否必选 | 示例值 | 描述 |
---|---|---|---|---|
ContentEncoding | String | 否 | Base64 | 返回的CommandContent的编码方式,默认为Base64。取值范围(不区分大小写): PlainText:返回明文形式的CommandContent Base64:返回Base64编码的CommandContent其余值均按照Base64处理 |
应用举例
使用RunCommand,可以以极简的方式完成命令的执行。比如我们有一台或一批实例,想要在创建实例之后安装MySQL。由于只需要安装一次,之后没有必要再保留该命令,所以很适合采用RunCommand。
DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "<accessKeyId>", "<accessSecret>");
IAcsClient client = new DefaultAcsClient(profile);
RunCommandRequest request = new RunCommandRequest();
request.setCommandContent("yum install mysql");
request.setType("RunShellScript");
request.setName("test_runcommand");
List<String> instanceIdList = new ArrayList<String>();
instanceIdList.add("i-XXXX");
request.setInstanceIds(instanceIdList);
try {
RunCommandResponse response = client.getAcsResponse(request);
System.out.println(new Gson().toJson(response));
} catch (ServerException e) {
e.printStackTrace();
} catch (ClientException e) {
System.out.println("ErrCode:" + e.getErrCode());
System.out.println("ErrMsg:" + e.getErrMsg());
System.out.println("RequestId:" + e.getRequestId());
}
总结
RunCommand的引入进一步完善了用户调用云助手的场景。对于命令内容相似,需要复用的场景,我们已经提供了命令支持自定义参数功能。而RunCommand关注于更轻量的命令执行,让用户能够更便捷、高效的执行云助手命令。