redis-cliのINFOコマンドの出力の改行はCRLF

redis-cliのINFOコマンドの出力の改行コードはドキュメント記載の通りLF(\n)ではなくCRLF(\r\n)になっている。

Lines can contain a section name (starting with a # character) or a property. All the properties are in the form of field:value terminated by \r\n.

$ redis-cli -h localhost INFO memory | head -5
# Memory
used_memory:1209255080
used_memory_human:1.13G
used_memory_rss:921198592
used_memory_rss_human:878.52M

$ redis-cli -h localhost INFO memory | head -5 | sed 's/\r/[Carriage Return]/'
# Memory[Carriage Return]
used_memory:1209255080[Carriage Return]
used_memory_human:1.13G[Carriage Return]
used_memory_rss:921198592[Carriage Return]
used_memory_rss_human:878.52M[Carriage Return]

出力して目で見るだけであれば問題ないが、awk等で抜き出して変数に入れると、その後の処理に困ることになる。

キャリッジリターンをBashで処理するときの問題

例えばused_memory/maxmemoryでメモリの使用率を計算するとする。

それぞれ以下のように変数に値をセットする。

redis_info=$(redis-cli -h localhost INFO memory)
used_memory=$(echo "$redis_info" | grep ^used_memory: | awk -F: '{print $2}')
maxmemory=$(  echo "$redis_info" | grep ^maxmemory:   | awk -F: '{print $2}')

計算式としては$used_memory / $maxmemoryなので、bcやawkに渡して計算する前にechoで変数展開後の計算式を確認する。

$ echo $used_memory
1209255080
$ echo $maxmemory
85207398912
$ echo "$used_memory / $maxmemory"
 / 85207398912

単体の変数としては問題なさそうに見えるが、変数を並べたり文字列を加えるとechoの表示がおかしくなる。

理由はキャリッジリターンが変数に含まれているから。

$ echo $maxmemory | sed 's/\r/[Carriage Return]/'
85207398912[Carriage Return]

$used_memoryの内容をechoが表示しても、キャリッジリターンによって行頭に戻ってから/ $maxmemoryを表示するため、$used_memoryの表示が消えてしまう。

redis-cliのINFOコマンドの出力を利用してスクリプトを作成する場合はキャリッジリターンを削除する

INFOコマンドの結果からキャリッジリターンをsedで消す。

redis_info=$(redis-cli -h localhost INFO memory | sed 's/\r//')
used_memory=$(echo "$redis_info" | grep ^used_memory: | awk -F: '{print $2}')
maxmemory=$(  echo "$redis_info" | grep ^maxmemory:   | awk -F: '{print $2}')

bcとawkで表示や繰り上げ繰り下げが少し違うが正しく計算できた。

$ echo "scale=4 $used_memory / $maxmemory" | bc
.0141
$ echo "$used_memory $maxmemory" | awk '{printf "%.4f\n", $1 / $2}'
0.0142