O bash possui um comando de cache embutido disponível (como mktemp ou sponge)?

5

Estou usando as ferramentas de linha de comando amazon ec2, e a ferramenta ec2-describe-instances é um pouco dolorosa devido aos 2-5 segundos necessários para fazer a solicitação e exibir a saída.

Estou pensando em usar a ferramenta fec2din descrita em esta questão para formatar a saída de ec2-describe-instances e queria saber qual seria a melhor maneira de armazenar em cache saída da chamada.

fec2din usa mktemp para criar um arquivo temporário e, em seguida, usa awk para formatar a saída.

Existe alguma ferramenta que eu poderia usar com um parâmetro TTL que só executaria ec2-describe-instances se o registro de data e hora no arquivo de cache fosse mais antigo que um certo tempo?

Seria interessante se houvesse um pequeno utilitário para fazer isso (como sponge para ajudar com stdout ).

    
por cwd 07.05.2012 / 17:45

4 respostas

1

Embora isso não resolva sua dúvida, recomendo usar o Amazon EC2 por meio do excelente boto , que é um pacote Python que fornece interfaces para o Amazon Web Services .

Ele praticamente cobre o mesmo terreno das Ferramentas da API do Amazon EC2 , mas não sofre com os dolorosos atrasos devido à confiança nas APIs AWS REST modernas e rápidas, enquanto as Ferramentas da API do EC2 são escritas em Java e usadas para usar as antigas e lentas APIs SOAP (não sei se elas podem ter mudado as a este respeito já, mas a sua experiência, bem como os ainda necessários Certificados AWS X.509 parecem sugerir o contrário).

Além disso, você não precisa mais usar esses Certificados AWS X.509 , mas pode usar a abordagem mais comum e flexível de hoje em dia por meio de um ID da chave de acesso da AWS e uma chave de acesso secreta da AWS , que também pode (e geralmente deve ser) fornecida por meio da identidade e acesso da AWS Gerenciamento (IAM) para evitar a exposição de suas principais credenciais da conta da AWS.

Além disso, boto é um candidato óbvio para orquestrar o uso diário da AWS por meio de scripts em Python - isso também pode ser feito com bash , mas você entendeu; )

Documentação

Você pode encontrar documentação e exemplos em boto: uma interface Python para o Amazon Web Services , que fornece decente (ou seja, mais ou menos completo) Referências da API (por exemplo, para EC2 ), bem como artigos introdutórios dedicados explicando o uso básico para vários serviços (mas ainda não todos), por exemplo Uma introdução à interface do EC2 do boto aborda o caso de uso em questão.

Além disso, você pode querer ler Boto Config para configurar seu ambiente (credenciais etc.) .

Uso

Você pode explorar o boto através do loop de leitura – eval – impressão do Python , isto é, iniciando python .

Quando estiver satisfeito com seus fragmentos, você poderá convertê-los em um script Python para uso independente.

Exemplo

Aqui está um exemplo abordando aproximadamente o seu caso de uso (ele pressupõe que você tenha configurado as credenciais em seu ambiente, conforme explicado em Boto Config ):

$ python
Python 2.7.2 (default, Jun 12 2011, 14:24:46)
Type "help", "copyright", "credits" or "license" for more information.
>>> import boto
>>> ec2 = boto.connect_ec2()
>>> instances = ec2.get_all_instances()
>>> instances
[Reservation:r-916d01f2, Reservation:r-3f7e055c, Reservation:r-c37209a0]

Ok, get_all_instances() realmente retornou uma lista de boto.ec2 .instance.Reservation , então aqui está uma indirecção chata no lugar (decorrente da API do EC2), que você não verá em outro lugar normalmente - os documentos já são conclusivos, mas vamos ver como descobrir isso por introspecção :

>>> dir(instances[0])
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', 
'__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', 
'__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 
'connection', 'endElement', 'groups', 'id', 'instances', 'item', 'owner_id', 
'region', 'startElement', 'stop_all']
>>> insts = instances[0].instances
>>> insts
[Instance:i-5d9a593a]

É mais ou menos assim, então, finalmente, você deseja ver os valores de atributo de i-5d9a593a (a maioria dos atributos foi omitida para brevidade e privacidade):

>>> vars(insts[0])
{'kernel': u'aki-825ea7eb', 'private_dns_name': '', 'id': u'i-5d9a593a', 
'monitored': False, 'state': u'stopped', 'architecture': u'x86_64',  
 'public_dns_name': '', 'ip_address': None, 'placement': u
'us-east-1a', 'ami_launch_index': u'0', 'dns_name': '', 'region': RegionInfo:us-east-1
# ...
}

Não é bem assim, mas Impressora de dados bonita (pprint) do Python para o resgate:

>>> import pprint
>>> pp = pprint.PrettyPrinter(indent=4)
>>> pp.pprint(vars(insts[0])) {   
    '_in_monitoring_element': False,
    'ami_launch_index': u'0',
    'architecture': u'x86_64',
    'dns_name': '',
    'hypervisor': u'xen',
    'id': u'i-5d9a593a',
    'instance_class': None,
    'instance_type': u'm1.medium',
    'ip_address': None,
    'kernel': u'aki-825ea7eb'
    # ...
    }
    
por 07.05.2012 / 18:09
1

Um utilitário sponge improvisado pode ser feito lendo linhas em uma matriz e, em seguida, exibindo-a, por exemplo:

sponge() {
    local line lines
    while IFS= read -r line; do
        lines+=( "$line" )
    done
    printf '%s\n' "${lines[@]}"
}

Em seguida, execute-o como command1 | sponge | command2 .

    
por 07.05.2012 / 20:54
0

Aqui está um recurso de armazenamento em cache muito bruto para o bash / ksh / zsh.

typeset -A output_cache
cache () {
  local IFS='
  ' ret=0
  if [[ -z ${output_cache["$*"]} ]]; then
    output_cache["$*"]=$(unset IFS; "$@")
    ret=$?
  fi
  echo "${output_cache["$*"]}"
  return $ret
}
uncache () {
  local IFS='
  '
  unset output_cache["$*"]
}

Exemplo:

$ cache mycommand --options        # takes a while
…
$ cache mycommand --options        # instantaneous
…
$ uncache mycommand --options      # remove a cache entry

Limitações:

  • Isso só faz sentido se a execução do comando produzir duas vezes a mesma saída a cada vez.
  • O cache não é compartilhado entre instâncias do shell.
  • Isso só funciona para comandos simples, não para pipelines, loops etc. (a menos que você use cache sh -c … ).
  • As entradas de cache que diferem apenas pela separação de palavras (por exemplo, mycommand "foo bar" vs. mycommand "foo" "bar" ) não são diferenciadas. Isso não deve ser um problema real na prática.
  • A primeira chamada do comando retorna seu código de retorno. As chamadas em cache retornam 0. Se você deseja retornar o código de retorno original, adicione uma matriz associativa para armazenar os códigos de retorno. Outro comportamento possível seria armazenar a saída do comando no cache apenas se o comando retornasse um status diferente de zero.
  • Apenas a saída padrão é salva, a saída no erro padrão ou outros descritores de arquivo não.
  • A saída vazia não é considerada em cache.
  • O número de novas linhas no final da saída é normalizado para 1. (Isso é fácil de corrigir, mas provavelmente é melhor assim na prática.)
  • Você não pode usar um alias após cache . Essa nuvem tem um efeito prateado: se você sempre deseja armazenar um comando em cache, pode alias-lo para cache mycommand .
  • Não há expiração. Existem muitos mecanismos de expiração potencialmente úteis (tente detectar relevância, mantenha um número máximo de entradas, dê às entradas um tempo para viver ...), não as implementarei como parte dessa resposta.
por 08.05.2012 / 02:48
-2
#!/bin/sh
PROG="$(basename $0)"
DIR="${HOME}/.cache/${PROG}"
mkdir -p "${DIR}"
EXPIRY=600 # default to 10 minutes
[ "$1" -eq "$1" ] 2>/dev/null && EXPIRY=$1 && shift
CMD="$@"
HASH=$(echo "$CMD" | md5sum | awk '{print $1}')
CACHE="$DIR/$HASH"
test -f "${CACHE}" && [ $(expr $(date +%s) - $(date -r "$CACHE" +%s)) -le $EXPIRY ] || "$CMD" > "${CACHE}"
cat "${CACHE}"
    
por 03.01.2016 / 06:59