# coding=utf-8
# If the Python sdk is not installed, run 'sudo pip install aliyun-python-sdk-ecs'.
# Make sure you're using the latest sdk version.
# Run 'sudo pip install --upgrade aliyun-python-sdk-ecs' to upgrade.
import json
import sys
import base64
import time
import logging
import os
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ClientException
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkecs.request.v20140526.RunCommandRequest import RunCommandRequest
from aliyunsdkecs.request.v20140526.DescribeInvocationResultsRequest import DescribeInvocationResultsRequest
from aliyunsdkecs.request.v20140526.RebootInstancesRequest import RebootInstancesRequest
from aliyunsdkecs.request.v20140526.DescribeInstancesRequest import DescribeInstancesRequest
# Configure the log output formatter
logging.basicConfig(level=logging.INFO,
format="%(asctime)s %(name)s [%(levelname)s]: %(message)s",
datefmt='%m-%d %H:%M')
logger = logging.getLogger()
# 请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID 和 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
# 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例使用环境变量获取 AccessKey 的方式进行调用,仅供参考,建议使用更安全的 STS 方式。
access_key = os.environ['ALIBABA_CLOUD_ACCESS_KEY_ID']
access_key_secret = os.environ['ALIBABA_CLOUD_ACCESS_KEY_SECRET']
region_id = '<yourRegionId>' # 请填入您获取的Region ID
client = AcsClient(access_key, access_key_secret, region_id)
def base64_decode(content, code='utf-8'):
if sys.version_info.major == 2:
return base64.b64decode(content)
else:
return base64.b64decode(content).decode(code)
def get_invoke_result(invoke_id):
request = DescribeInvocationResultsRequest()
request.set_accept_format('json')
request.set_InvokeId(invoke_id)
response = client.do_action_with_exception(request)
response_details = json.loads(response)["Invocation"]["InvocationResults"]["InvocationResult"]
dict_res = { detail.get("InstanceId",""):{"status": detail.get("InvocationStatus",""),"output":base64_decode(detail.get("Output",""))} for detail in response_details }
return dict_res
def get_instances_status(instance_ids):
request = DescribeInstancesRequest()
request.set_accept_format('json')
request.set_InstanceIds(instance_ids)
response = client.do_action_with_exception(request)
response_details = json.loads(response)["Instances"]["Instance"]
dict_res = { detail.get("InstanceId",""):{"status":detail.get("Status","")} for detail in response_details }
return dict_res
def run_command(cmdtype,cmdcontent,instance_ids,timeout=60):
"""
cmdtype: 命令类型: RunBatScript;RunPowerShellScript;RunShellScript
cmdcontent: 命令内容
instance_ids 实例ID列表
"""
try:
request = RunCommandRequest()
request.set_accept_format('json')
request.set_Type(cmdtype)
request.set_CommandContent(cmdcontent)
request.set_InstanceIds(instance_ids)
# 执行命令的超时时间,单位s,默认是60s,请根据执行的实际命令来设置合适的超时时间
request.set_Timeout(timeout)
response = client.do_action_with_exception(request)
invoke_id = json.loads(response).get("InvokeId")
return invoke_id
except Exception as e:
logger.error("run command failed")
def reboot_instances(instance_ids,Force=False):
"""
instance_ids: 需要重启的实例列表
Force: 是否强制重启,默认否
"""
request = RebootInstancesRequest()
request.set_accept_format('json')
request.set_InstanceIds(instance_ids)
request.set_ForceReboot(Force)
response = client.do_action_with_exception(request)
def wait_invoke_finished_get_out(invoke_id,wait_count,wait_interval):
for i in range(wait_count):
result = get_invoke_result(invoke_id)
if set([res["status"] for _,res in result.items()]) & set(["Running","Pending","Stopping"]):
time.sleep(wait_interval)
else:
return result
return result
def wait_instance_reboot_ready(ins_ids,wait_count,wait_interval):
for i in range(wait_count):
result = get_instances_status(ins_ids)
if set([res["status"] for _,res in result.items()]) != set(["Running"]):
time.sleep(wait_interval)
else:
return result
return result
def run_task():
# 设置云助手命令的命令类型
cmdtype = "RunShellScript"
# 设置云助手命令的命令内容
cmdcontent = """
#!/bin/bash
echo helloworld
"""
# 设置超时时间
timeout = 60
# 请填入需要执行命令并重启的实例的ID
ins_ids= ["i-bp185fcs****","i-bp14wwh****","i-bp13jbr****"]
# 执行命令
invoke_id = run_command(cmdtype,cmdcontent,ins_ids,timeout)
logger.info("run command,invoke-id:%s" % invoke_id)
# 等待命令执行完成,循环查询10次,每次间隔5秒,查询次数和间隔请根据实际情况配置
invoke_result = wait_invoke_finished_get_out(invoke_id,10,5)
for ins_id,res in invoke_result.items():
logger.info("instance %s command execute finished,status: %s,output:%s" %(ins_id,res["status"],res["output"]))
# 重启实例
logger.warn("reboot instance Now")
reboot_instances(ins_ids)
time.sleep(5)
# 等待实例重启至Running状态,循环查询30次,每次间隔10秒
reboot_result = wait_instance_reboot_ready(ins_ids,30,10)
logger.warn("reboot instance Finished")
for ins_id,res in reboot_result.items():
logger.info("instance %s status: %s" %(ins_id,res["status"]))
if __name__ == '__main__':
run_task()
这段代码是使用阿里云的Python SDK库来执行在特定ECS实例上的一些操作,一步步解析这段代码。
import json
import sys
import base64
import time
import logging
import os
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ClientException
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkecs.request.v20140526.RunCommandRequest import RunCommandRequest
from aliyunsdkecs.request.v20140526.DescribeInvocationResultsRequest import DescribeInvocationResultsRequest
from aliyunsdkecs.request.v20140526.RebootInstancesRequest import RebootInstancesRequest
from aliyunsdkecs.request.v20140526.DescribeInstancesRequest import DescribeInstancesRequest
上面的代码是一系列的导入命令,这将导入我们执行任务所需的所有模块和函数。
logging.basicConfig(level=logging.INFO,
format="%(asctime)s %(name)s [%(levelname)s]: %(message)s",
datefmt='%m-%d %H:%M')
logger = logging.getLogger()
这部分用于配置日志输出的格式和获取logger对象,所有的日志将会按照这个格式进行输出,配置日志对于追踪程序的执行和调试很有帮助。
access_key = os.environ['ALIBABA_CLOUD_ACCESS_KEY_ID']
access_key_secret = os.environ['ALIBABA_CLOUD_ACCESS_KEY_SECRET']
region_id = '<yourRegionId>'
client = AcsClient(access_key, access_key_secret, region_id)
这部分代码是用于获取你的阿里云账户认证密钥并初始化一个用于请求阿里云API的客户端。
剩下的部分定义了一些函数,每个函数都执行一个特定的操作:
base64_decode(content, code='utf-8')
函数负责对base64编码的内容进行解码。get_invoke_result(invoke_id)
这个函数根据invoke_id获取服务器执行命令的结果。get_instances_status(instance_ids)
这个函数通过给定的实例ID列表查询每个实例当前的状态。run_command(cmdtype,cmdcontent,instance_ids,timeout=60)
这个函数根据指定的参数执行命令操作。reboot_instances(instance_ids,Force=False)
这个函数是用于重启指定的实例列表。wait_invoke_finished_get_out(invoke_id,wait_count,wait_interval)
这个函数是等待命令执行完毕并获取结果。wait_instance_reboot_ready(ins_ids,wait_count,wait_interval)
这个函数是用于等待实例重启并达到Running状态。
最后的run_task()
函数是主要的执行过程,它首先运行命令,等待命令执行完成,然后重启实例,并等待实例重启至Running状态。