Todos os produtos
Search
Central de documentação

CDN:Use a CLI do EdgeScript para gerenciar scripts

Última atualização: Jul 03, 2026

A CLI do EdgeScript (ES) permite publicar scripts da máquina local nos ambientes de teste e produção, além de consultar, modificar ou excluir esses scripts sem usar o console.

Pré-requisitos

Antes de começar, verifique se você tem:

  • Um usuário RAM com as permissões necessárias do CDN

  • O AccessKey ID e o AccessKey secret do usuário RAM

  • Python 2 instalado na máquina local

Configure a CLI

Crie os arquivos do projeto

  1. Crie uma pasta para o projeto, por exemplo, cdn-api.

  2. Na pasta, crie um arquivo chamado aliyun.ini para armazenar as credenciais do usuário RAM:

    [Credentials]
    accesskeyid = <your-access-key-id>
    accesskeysecret = <your-access-key-secret>
  3. Na mesma pasta, crie um arquivo chamado es.py e cole o seguinte script Python:

    #!/usr/bin/python
    # -*- coding:utf-8 -*-
    
    import sys, os
    import urllib, urllib2
    import base64
    import hmac
    import hashlib
    from hashlib import sha1
    import time
    import uuid
    import json
    from optparse import OptionParser
    import ConfigParser
    import traceback
    import urllib2
    
    access_key_id = '';
    access_key_secret = '';
    cdn_server_address = 'https://cdn.aliyuncs.com'
    CONFIGFILE = os.getcwd() + '/aliyun.ini'
    CONFIGSECTION = 'Credentials'
    cmdlist = '''
    
       1. Publish the ES rule to the simulated environment or production environment
          ./es.py action=push_test_env domain=<domain> rule='{"pos":"<head|foot>","pri":"0-999","rule_path":"<the es code path>","enable":"<on|off>"}'
          ./es.py action=push_product_env domain=<domain> rule='{"pos":"<head|foot>","pri":"0-999","rule_path":"<the es code path>","enable":"<on|off>","configid":"<configid>"}'
    
       2. Query the ES rule in the simulated environment or production environment
          ./es.py action=query_test_env domain=<domain>
          ./es.py action=query_product_env domain=<domain>
    
       3. Delete the ES rule in the simulated environment or production environment
          ./es.py action=del_test_env domain=<domain> configid=<configid>
          ./es.py action=del_product_env domain=<domain> configid=<configid>
    
       4. Publish the ES rule from the simulated to production environment, or Rollback the ES rule in the simulated environment
          ./es.py action=publish_test_env domain=<domain>
          ./es.py action=rollback_test_env domain=<domain>
    '''
    
    def percent_encode(str):
        res = urllib.quote(str.decode(sys.stdin.encoding).encode('utf8'), '')
        res = res.replace('+', '%20')
        res = res.replace('*', '%2A')
        res = res.replace('%7E', '~')
        return res
    
    def compute_signature(parameters, access_key_secret):
        sortedParameters = sorted(parameters.items(), key=lambda parameters: parameters[0])
    
        canonicalizedQueryString = ''
        for (k,v) in sortedParameters:
            canonicalizedQueryString += '&' + percent_encode(k) + '=' + percent_encode(v)
    
        stringToSign = 'GET&%2F&' + percent_encode(canonicalizedQueryString[1:])
    
        h = hmac.new(access_key_secret + "&", stringToSign, sha1)
        signature = base64.encodestring(h.digest()).strip()
        return signature
    
    def compose_url(user_params):
        timestamp = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
    
        parameters = { \
            'Format'        : 'JSON', \
            'Version'       : '2018-05-10', \
            'AccessKeyId'   : access_key_id, \
            'SignatureVersion'  : '1.0', \
            'SignatureMethod'   : 'HMAC-SHA1', \
            'SignatureNonce'    : str(uuid.uuid1()), \
            'Timestamp'         : timestamp, \
        }
    
        for key in user_params.keys():
            parameters[key] = user_params[key]
    
        signature = compute_signature(parameters, access_key_secret)
        parameters['Signature'] = signature
        url = cdn_server_address + "/?" + urllib.urlencode(parameters)
        return url
    
    def make_request(user_params, quiet=False):
        url = compose_url(user_params)
    
        try:
            req = urllib2.Request(url)
            r = urllib2.urlopen(req)
        except urllib2.HTTPError, err:
            print "Response Code:\n============="
            print err
            body=err.read()
            body_json = json.loads(body)
            body_str =json.dumps(body_json,indent=4)
            print "\nResponse Info:\n=============="
            print body_str
            return
    
        if r.getcode() == 200:
            print "Response Code:\n=============\n200 OK"
        print "\nResponse Info:\n=============="
        body=r.read()
        body_json = json.loads(body)
        body_str =json.dumps(body_json,indent=4)
        print body_str
    
    def configure_accesskeypair(args, options):
        if options.accesskeyid is None or options.accesskeysecret is None:
            print("config miss parameters, use --id=[accesskeyid] --secret=[accesskeysecret]")
            sys.exit(1)
        config = ConfigParser.RawConfigParser()
        config.add_section(CONFIGSECTION)
        config.set(CONFIGSECTION, 'accesskeyid', options.accesskeyid)
        config.set(CONFIGSECTION, 'accesskeysecret', options.accesskeysecret)
        cfgfile = open(CONFIGFILE, 'w+')
        config.write(cfgfile)
        cfgfile.close()
    
    def setup_credentials():
        config = ConfigParser.ConfigParser()
        try:
            config.read(CONFIGFILE)
            global access_key_id
            global access_key_secret
            access_key_id = config.get(CONFIGSECTION, 'accesskeyid')
            access_key_secret = config.get(CONFIGSECTION, 'accesskeysecret')
        except Exception, e:
            print traceback.format_exc()
            print("can't get access key pair, use config --id=[accesskeyid] --secret=[accesskeysecret] to setup")
            sys.exit(1)
    
    def parse_args(user_params):
        req_args = {}
    
        if user_params['action'] == 'push_test_env' or user_params['action'] == 'push_product_env':
            if not user_params.has_key('domain') or not user_params.has_key('rule'):
                parser.print_help()
                sys.exit(0)
    
            data = []
            for rule in user_params['rule']:
                rule_cfg = {
                    'functionId' : 180,
                    'functionName' : 'edge_function',
                    'functionArgs' : []
                }
                for k in rule:
                    arg_cfg = {}
                    if k == 'configid':
                        rule_cfg['configId'] = int(rule[k])
                    elif k == 'rule_path':
                        try:
                            f = open(rule[k], "r")
                            code = f.read()
                        except IOError:
                            print "io error"
                            sys.exit(0)
                        else:
                            f.close()
                        arg_cfg['argName'] = 'rule'
                        arg_cfg['argValue'] = code
                        rule_cfg['functionArgs'].append(arg_cfg)
                    else:
                        arg_cfg['argName'] = k
                        arg_cfg['argValue'] = rule[k]
                        rule_cfg['functionArgs'].append(arg_cfg)
                data.append(rule_cfg)
            rule_str = json.dumps(data)
    
            if user_params['action'] == 'push_test_env':
                req_args = {'Action':'SetCdnDomainStagingConfig', 'DomainName':user_params['domain'], 'Functions':rule_str}
            else:
                req_args = {'Action':'BatchSetCdnDomainConfig', 'DomainNames':user_params['domain'], 'Functions':rule_str}
    
        elif user_params['action'] == 'query_test_env':
            if not user_params.has_key('domain'):
                parser.print_help()
                sys.exit(0)
            req_args = {'Action':'DescribeCdnDomainStagingConfig', 'DomainName':user_params['domain'], 'FunctionNames':'edge_function'}
    
        elif user_params['action'] == 'query_product_env':
            if not user_params.has_key('domain'):
                parser.print_help()
                sys.exit(0)
            req_args = {'Action':'DescribeCdnDomainConfigs', 'DomainName':user_params['domain'], 'FunctionNames':'edge_function'}
    
        elif user_params['action'] == 'del_test_env':
            if not user_params.has_key('domain') or not user_params.has_key('configid'):
                parser.print_help()
                sys.exit(0)
            req_args = {'Action':'DeleteSpecificStagingConfig', 'DomainName':user_params['domain'], 'ConfigId':user_params['configid']}
    
        elif user_params['action'] == 'del_product_env':
            if not user_params.has_key('domain') or not user_params.has_key('configid'):
                parser.print_help()
                sys.exit(0)
            req_args = {'Action':'DeleteSpecificConfig', 'DomainName':user_params['domain'], 'ConfigId':user_params['configid']}
    
        elif user_params['action'] == 'publish_test_env':
            if not user_params.has_key('domain'):
                parser.print_help()
                sys.exit(0)
            req_args = {'Action':'PublishStagingConfigToProduction', 'DomainName':user_params['domain'], 'FunctionName':'edge_function'}
    
        elif user_params['action'] == 'rollback_test_env':
            if not user_params.has_key('domain'):
                parser.print_help()
                sys.exit(0)
            req_args = {'Action':'RollbackStagingConfig', 'DomainName':user_params['domain'], 'FunctionName':'edge_function'}
    
        else:
            parser.print_help()
            sys.exit(0)
    
        return req_args
    
    if __name__ == '__main__':
        parser = OptionParser("%s Action=action Param1=Value1 Param2=Value2 %s\n" % (sys.argv[0], cmdlist))
        parser.add_option("-i", "--id", dest="accesskeyid", help="specify access key id")
        parser.add_option("-s", "--secret", dest="accesskeysecret", help="specify access key secret")
    
        (options, args) = parser.parse_args()
        if len(args) < 1:
            parser.print_help()
            sys.exit(0)
    
        if args[0] == 'help':
            parser.print_help()
            sys.exit(0)
        if args[0] != 'config':
            setup_credentials()
        else: #it's a configure id/secret command
            configure_accesskeypair(args, options)
            sys.exit(0)
    
        user_params = {}
        idx = 1
        if sys.argv[1].lower().startswith('action='):
            _, value = sys.argv[1].split('=')
            user_params['action'] = value
            idx = 2
        else:
            parser.print_help()
            sys.exit(0)
    
        for arg in sys.argv[idx:]:
            try:
                key, value = arg.split('=', 1)
                if key == 'rule': # push_test_env / push_product_env
                    if not user_params.has_key('rule'):
                        user_params['rule'] = []
                    user_params['rule'].append(json.loads(value))
                else:
                    user_params[key.strip()] = value
            except ValueError, e:
                print(e.read().strip())
                raise SystemExit(e)
    
        req_args = parse_args(user_params)
        make_request(req_args)

Configure as credenciais

Execute o comando abaixo para armazenar o par de AccessKeys no arquivo aliyun.ini:

python ./es.py config --id=<your-access-key-id> --secret=<your-access-key-secret>

Verifique se as credenciais foram salvas:

cat aliyun.ini

Saída esperada:

[Credentials]
accesskeyid = <your-access-key-id>
accesskeysecret = <your-access-key-secret>

Gerencie scripts

Todos os comandos usam o parâmetro action para especificar a operação. Substitua <domain> pelo nome do domínio acelerado em cada comando.

Publique um script

Envie um script para o ambiente de teste para validá-lo antes da publicação oficial:

./es.py action=push_test_env domain=<domain> rule='{"pos":"head","pri":"10","rule_path":"./m3u8.es","enable":"on"}'

Para enviar um script diretamente ao ambiente de produção:

./es.py action=push_product_env domain=<domain> rule='{"pos":"head","pri":"10","rule_path":"./m3u8.es","enable":"on","configid":"12345"}'

O parâmetro rule aceita os campos a seguir:

Campo

Obrigatório

Descrição

Valores válidos

Padrão

pos

Sim

Posição de execução do script

head, foot

pri

Sim

Prioridade entre scripts na mesma posição. 0 indica a prioridade mais alta; 999, a mais baixa.

0999

enable

Sim

Indica se o script está ativo

on, off

rule

Sim

Conteúdo do script. Ao usar a CLI, forneça rule_path; a CLI lê o arquivo e passa o conteúdo neste campo.

String de conteúdo do script

rule_path

Apenas CLI

Caminho do arquivo EdgeScript local. A CLI lê esse arquivo e envia o conteúdo como campo rule.

String de caminho de arquivo

configid

Obrigatório ao modificar

ID de configuração de um script existente. Omita na criação; obrigatório na modificação.

ID de configuração

brk

Não

Interrompe a execução de scripts subsequentes se este script for executado

on, off

off

testip

Não

Restringe a execução do script a solicitações de um endereço IP de cliente específico

String de endereço IP

Vazio (todas as solicitações)

option

Não

Campo de extensão. Defina como _es_dbg=<signature> para ativar a depuração de cabeçalho de resposta.

_es_dbg=<signature>

É possível especificar vários parâmetros rule em um único comando para enviar múltiplos scripts simultaneamente.

Sobre IDs de configuração

O sistema gera automaticamente um ID de configuração (configid) ao criar um script para um nome de domínio. Não é necessário fornecer esse ID durante a criação. Para modificar um script existente, consulte-o primeiro para obter o ID de configuração e inclua "configid":"<configid>" no campo rule. Para mais detalhes, consulte Notas de uso sobre ConfigId.

Consulte scripts

Liste todos os scripts EdgeScript de um nome de domínio:

# Staging environment
./es.py action=query_test_env domain=<domain>

# Production environment
./es.py action=query_product_env domain=<domain>

Exclua um script

Exclua um script pelo ID de configuração. Execute uma consulta antes caso não saiba o ID.

# Staging environment
./es.py action=del_test_env domain=<domain> configid=<configid>

# Production environment
./es.py action=del_product_env domain=<domain> configid=<configid>

Promova scripts de teste para produção

Após validar os scripts no ambiente de teste, promova-os para produção:

./es.py action=publish_test_env domain=<domain>

Reverta scripts

Reverta o ambiente de teste para a configuração anterior:

./es.py action=rollback_test_env domain=<domain>

Depure scripts

Para ativar a depuração de cabeçalho de resposta, defina o campo option como _es_dbg=<signature> ao enviar um script:

./es.py action=push_test_env domain=<domain> rule='{"pos":"head","pri":"10","rule_path":"./m3u8.es","enable":"on","configid":"12345","option":"_es_dbg=123"}'

Também é possível ativar a depuração pelo console do Alibaba Cloud CDN, caso haja suporte ao WebIDE.

Depois de ativar a depuração, inclua _es_dbg=<signature> no cabeçalho da solicitação de teste. A resposta incluirá o cabeçalho de depuração a seguir:

X-DEBUG-ES-TRACE-RULE-{Script ID}

O valor de rastreamento segue este formato: _<row-number>_<function-name>(<input>):<return-value>{_<execution-duration>}

Esse valor mostra o fluxo de controle do script, incluindo cada chamada de função, entrada, valor de retorno e tempo de execução.

Próximos passos