ようへいの日々精進XP

よかろうもん

bash の select は令和の時代も役に立つ, その一例

tl;dr

ホントにちょっとした運用ツールを bash で作っていて, 複数の選択肢をリストアップしてメニューとして選択出来るようにしたいなーと思っていたら, bash には select 文という超絶便利な構文が用意されていたので使ってみました.

man bash

https://linuxjm.osdn.jp/html/GNU_bash/man1/bash.1.html より引用させて頂きつつ, 重要だなと思ったところをかいつまんで.

select name [ in word ] ; do list ; done in に続く単語のリストが展開され、要素のリストが生成されます。 展開された単語の集合が番号付きで標準エラー出力に出力されます。 「in word」が省略された場合、 位置パラメータが出力されます (後述の パラメータ を参照)。続いて PS3 プロンプトが表示され、標準入力から 1 行の読み込みが行われます。

  • list が展開され, 各要素が番号付きで標準エラーに出力される
  • PS3 プロンプトが表示されて, 標準入力から番号の入力を待つ

PS3 を上書きすることで, オリジナルのプロンプトを出力出来るということですな.

読み込んだ行は変数 REPLY に格納されます。 break コマンドが実行されるまで、 選択を行うたびに list が実行されます。 select の終了ステータスは、 list 中で最後に実行したコマンドの終了ステータスですが、 コマンドが全く実行されなかった場合には 0 となります。

  • 読み込んだ行は変数の $REPLY に格納される = 選択した文字が格納される (以下の実行例だと, )

以下, 実行例.

#!/usr/bin/env bash

PS3="番号を選択して下さい. Enter 'q' for exit! > "
menu="foo bar baz"
item=""
select item in $menu
do
  if [ "${REPLY}" = "q" ]; then
      echo "終了します."
      exit 0
  fi

  if [ -n "${item}" ]; then
    break
  else
    echo "invalid selection."
  fi
done

echo "${REPLY} を選択しました. 値は ${item} です."

以下, 実行例です.

f:id:inokara:20200418080209g:plain

いい感じです.

若干の

偏りがありますが, 最近, 少しずつ Kubernetes を触る機会が増えてきていて Kubernetes 触る上で複数のクラスタや Pod を切り替えたいというシチュエーションが出てきております.

Kubernetes クラスタを選択したい

複数のクラスタを管理していると, クラスタを切り替えることはあると思います. いちいち kubectl config get-clusters で確認するのは飽きてきたので, 以下のようなスクリプトを作ってみました.

#!/usr/bin/env bash

PS3="番号を選択して下さい. Enter 'q' for exit! > "
menu="$(kubectl config get-clusters | sed '1d' | tr '\n' ' ')"
item=""
select item in $menu
do
  # If enter 'q', exit this shell.
  if [ "${REPLY}" = "q" ]; then
      echo "終了します."
      exit 0
  fi

  if [ -n "${item}" ]; then
    break
  else
    echo "invalid selection."
  fi
done

kubectl config use-context "${item}"

kubectl config get-clusters の実行結果は以下の通りですが, この実行結果をリスト化しているのですが, kubectl get のような --no-headers が利用出来ないのが玉にキズです.

$ kubectl config get-clusters
NAME
gke_xxxxxxxxxx_asia-northeast1-a_oreno1-cluster-dev
gke_xxxxxxxxxx_asia-northeast1-a_oreno2-cluster-dev
docker-desktop

他に良いツールがあったら教えて下さい.

Kubernetes Pod を選択したい

Pod のログを確認しようとした時に, いちいち kubectl get pods して Pod の NAME を確認することが辛かったので, 以下のようなスクリプトを作ってみました.

#!/usr/bin/env bash

PS3="番号を選択して下さい. Enter 'q' for exit! > "
menu="$(kubectl get pods --no-headers --output=custom-columns=NAME:.metadata.name | tr '\n' ' ')"
item=""
select item in $menu
do
  # If enter 'q', exit this shell.
  if [ "${REPLY}" = "q" ]; then
      echo "終了します."
      exit 0
  fi

  if [ -n "${item}" ]; then
    break
  else
    echo "invalid selection."
  fi
done

kubectl logs -f "${item}"

以下, 実行例です.

f:id:inokara:20200418083132g:plain

きっともっと良いツールが実は出回っているんだろうなあ... kubectl を直接叩くのは中学生までなんじゃ... という不安を抱えていますが, 今の所はこれで間に合っています.

以上

bash の select は令和の時代も役に立つ, その一例でした.