Existe um comando ou utilitário shell para armazenar em cache a saída do processo?

1

Espero que este seja o lugar certo para perguntar.

Existe uma ferramenta unix que funciona de forma semelhante a esta?

# invokes echo, saves to cache (using command with arguments as key), returns "hi"
cache 10 echo hi 

# wait 2 seconds
sleep 2

# doesn't invoke echo, from cache returns "hi"
cache 10 echo hi 

# wait 10 seconds
sleep 10

# with cache expired, invokes echo, returns "hi"
cache 10 echo hi 

Obviamente, o eco não seria o caso de uso real.

Basicamente armazena em cache STDOUT, STDERR e status para um determinado comando + argumentos, então a próxima chamada para o mesmo processo não precisa ser executada novamente.

Eu poderia escrever um script que faça isso, mas imaginei se havia um no conjunto de ferramentas unix que eu não conhecia.

    
por Dan2552 03.01.2017 / 14:53

5 respostas

1

Você pode colocar o resultado em um arquivo e depois lê-lo de volta a partir desse arquivo ...

tmpDir=/tmp/$$
rm -rf "$tmpDir"
mkdir "$tmpDir"

echo cmd1 > "$tmpDir"/cmd1_stdout 2> "$tmpDir"/cmd1_stderr
echo $? > "$tmpDir"/cmd1_exitcode

# Retrieving output of cmd1:
( cat "$tmpDir"/cmd1_stdout ; cat "$tmpDir"/cmd1_stderr 1>&2; exit $(cat "$tmpDir"/cmd1_exitcode) )

A partir disso, podemos definir uma função "cache". Esta versão precisa de um personagem que nunca usaremos como argumento. Por exemplo, a vírgula ",". Você pode alterá-lo na linha "IFS =,"

tmpDir=/tmp/$$
rm -rf "$tmpDir"
mkdir "$tmpDir"

cache() {

 IFS=, cmd="$*"
 if [ -f "$tmpDir/$cmd"_exitcode ]; then 
   cat "$tmpDir/$cmd"_stdout
   cat "$tmpDir/$cmd"_stderr 1>&2
   return $(cat "$tmpDir"/cmd1_exitcode)
 fi

   # This line is bash-only:
 "$@" 2> >(tee "$tmpDir/$cmd"_stderr 1>&2) > >(tee "$tmpDir/$cmd"_stdout)
 local e=$?
 echo $e > "$tmpDir/$cmd"_exitcode

 return $e
}

O tempo limite pode ser implementado com "date +% s" e "stat -c% Y":

tmpDir=/tmp/$$
rm -rf "$tmpDir"
mkdir "$tmpDir"

cache() {

 local timeout=$1
 shift

 IFS=, cmd="$*"
 if [ -f "$tmpDir/$cmd"_exitcode ]; then 

   local now=$(date +%s)
   local fdate=$(stat -c %Y "$tmpDir/$cmd"_exitcode)

   if [ $((now-fdate)) -le $timeout ]; then 
     cat "$tmpDir/$cmd"_stdout
     cat "$tmpDir/$cmd"_stderr 1>&2
     return $(cat "$tmpDir/$cmd"_exitcode)
   fi

 fi

   # This line is bash-only:
 "$@" 2> >(tee "$tmpDir/$cmd"_stderr 1>&2) > >(tee "$tmpDir/$cmd"_stdout)
 local e=$?
 echo $e > "$tmpDir/$cmd"_exitcode

 return $e
}

A linha "bash only" pode ser substituída por:

  "$@" 2> "$tmpDir/$cmd"_stderr > "$tmpDir/$cmd"_stdout
  local e=$?
  cat "$tmpDir/$cmd"_stdout
  cat "$tmpDir/$cmd"_stderr 1>&2
    
por 03.01.2017 / 16:51
0

No meu conhecimento, não existe uma ferramenta padrão ou tradicional que funcione dessa maneira. No entanto, a pesquisa por "cache stdout" levou-me ao link , que parece ser uma ferramenta que faz o que você quer.

    
por 03.01.2017 / 15:02
0

Não tenho conhecimento de uma ferramenta genérica para fazer esse tipo de cache, mas estou ciente de uma ferramenta específica para armazenar em cache o resultado da compilação C ou Arquivos C ++, o ccache cache do compilador .

Isso armazena as fontes pré-processadas e os arquivos de código-objeto compilados e usa hashes com base no código-fonte e na assinatura do compilador para descobrir se deve usar o cache ou recompilar um arquivo.

Um cache genérico para o shell teria que similarmente hash o script, a assinatura de cada utilitário externo usado, etc., e também levar em conta que a saída de um script de shell pode depender da hora do dia (se usa date ) e muitos muitos outros fatores.

A criação de um cache para um único comando não seria benéfica, especialmente para echo , já que isso é feito na maioria dos shells e o processamento extra do cache só iria atrasá-lo (a menos que seja ecoado também chamado pesado externo utilitários através de substituições de comandos, etc.)

Eu não acho que valeria a pena no final, mas possivelmente apenas útil em um contexto muito específico, como o utilitário ccache para o cache de compilações, que é um problema um pouco mais limitado em seu escopo.

    
por 03.01.2017 / 15:14
0

O mecanismo mais comum para armazenar em cache a saída do comando em scripts de shell é atribuí-lo a uma variável. Isso é feito facilmente com um subshell. Ele não expira da maneira que um cache tradicional faz, mas aqueles que escrevem shell scripts geralmente acham isso aceitável. Aqui está seu script acima usando um subshell e uma variável

HI=$(echo hi)
echo $HI
sleep 2
echo $HI
sleep 10
echo $HI

Outra alternativa é criar uma função de cache no shell script. Algo como ...

cache() {
expiry=$1
cmd=$2-
cache=/tmp/{$2-}_cache

if test "'find -not -newermt '-30 seconds' -delete ${cache}'"; then
$cmd |tee "$cache"
else
cat "$cache"
fi
}
    
por 03.01.2017 / 16:36
-1

use este link

git clone link

vá construir main.go

./ main -c [seu comando] -t [tempo de cache]

    
por 11.12.2018 / 07:51