Help us understand the problem. What is going on with this article?

shellでTTL付きのキャッシュをしたい

More than 3 years have passed since last update.

こんな感じ

sleep 3 ; echoの結果を最大5秒間キャッシュしている様子。

cache-ttl-on-sh.gif

キャッシュの実装

実装はこのあたりに置いてある。

TTL付きのキャッシュを実装するにあたり、シェルで実現するならファイルに保存しておいて、作成日時はそのファイルのメタ情報を利用すれば楽。

また、やろうと思えば更新日時と作成日時がどちらも取れるので、細かいTTLの実装も可能。

stat -c %Yコマンドで指定したファイルの最終更新日時のepoch秒を取得できる。
それと現在時刻を比べて指定した時間より経過していたら...という処理を書くことでTTLを実装する。

statを使ってファイルの有効期限判定するには以下のようにする。

$ touch -d '1day ago' hoge.txt
$ [ $(( $(date +%s) - $(stat -c %Y hoge.txt) )) -gt $((60 * 60 * 25)) ] && echo 'true' || echo 'false'
false
$ [ $(( $(date +%s) - $(stat -c %Y hoge.txt) )) -gt $((60 * 60 * 23)) ] && echo 'true' || echo 'false'
true

キャッシュを保存するファイルのパスとTTL、実行するコマンドを渡せるようにするとこんな感じになった。

# TTL的に無効かどうか
function is_too_old() {
  local file=$1
  local ttl=$2 # seconds
  if [ -f $file ]; then
    [ $(( $(date +%s) - $(stat -c %Y "$1") )) -gt $ttl ]
  else
    false
  fi
}

# TTLを考慮して読み出す
function read_from_cache() {
  local cache=$1
  local ttl=$2  # seconds
  local command=$3
  if $(is_too_old $cache $ttl);then
    local result=$(sh -c "$command")
    if [ -z $result ]; then
      return
    else
      echo $result > $cache
    fi
  fi
  cat $cache
}

ちなみにMacだとgnubinを入れる必要がある。
テキスト処理のための標準的なコマンド群の OS X への導入手順 - Qiita

コードを読めばわかるが、例えばgcloud projects listの結果を1日キャッシュするには、

read_from_cache ./cache.txt $((60 * 60 * 24)) "gcloud projects list"

みたいにやれば良い。

"読み込み中"の表示

昔書いた記事に大体ある。
Zshで長い処理をしている間に読込中を表示する - Qiita

loadingコマンドはgithubにおいてある。

読み込み中を表示するあたりの実装はこうなる。

# job制御を無効化してバックグラウンド実行しているプロセスのIDが表示されるのを防ぐ
set +m
# loadingをバックグラウンド実行して表示
loading 1000 &
local loading_pid=$!

# 何か重い処理をする
local result=$(sh -c "$command")

# loadingを消す
kill -INT $loading_pid &>/dev/null
# loadingがkillされるのを待つ
sleep 0.1
# job制御を有効に戻す
set -m

ジョブ制御を無効にしてプロセスIDが表示されてしまうのを防ぐのがポイント。

$ sleep 10000 &  # IDが表示される
[1] 89535
$ kill $!  # IDが表示される
[1]  + terminated  sleep 10000
$ set +m
$ sleep 10000 &  # IDが表示されない
$ kill $!  # IDが表示されない
$ set -m
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away