LoginSignup
0
0

More than 1 year has passed since last update.

bashスクリプトで対話型コマンドを実行するには

Last updated at Posted at 2021-07-01

bashの中で対話型コマンドを実行する時の課題

シェルの中で対話型コマンドを実行するとき、それも対話内容によって複雑な処理が必要かつ、入力が変わる時、コマンドへの入力方法がわからない
例えば、letsencrypt のワイルドーカード証明証の発行などがそれ。

letsencrypt のワイルドーカード証明証では、対話型コマンドの中で、自身のDNSにTXTレコードを指定の値で作れって指示があり、それを設定した後にDNSが公開されるまで待って「改行」を入力する必要があります。 
簡単な対話型の実現なら expect コマンドでもいいが、上記のような処理では対応が難しい。

で、どう実現するか? コマンドの出力を受け取るのは簡単ですが、難しいのは入力。yesコマンドや echoを pipe で繋ぐと、待って欲しいのに勝手に入力してしまう。 このタイミングをコントロールする方法があります。 

実現方法

bash
touch input.txt
status=0
tail -f input.txt | {実行したいコマンド} | while read -r res;
do
    if [[ $status == 1 ]]; then
       {status1 + 次の入力(res)を使って、実際のコマンド処理}  [*1]
       echo "" >> input.txt     # ⭐️ここがポイント!! これでコマンドに入力できます!
       status=2
    elif [[ $res == {コマンドの対話出力でフックしたい文字列[*2]}* ]]; then
        status=1
    fi
done
rm -f input.txt
  1. letsencrypt のワイルドーカード証明証なら、ここでDNS TXTレコードに指定された値を設定する。DNS公開が安定するまでsleepした方が良いので、 sleep 300 などをコマンド実行後に入れる。
  2. ここに _acme-challenge.{ドメイン名} を入れれば、次の行で指定値を出力するので、そこでDNS TXTレコードを作るわけです。 それが [*1]のコマンドです。

まとめ

ポイントは、以下の形で、tail -f で入力できるようにし、read でコマンド出力を参照しながら必要に応じて tail -f で監視するファイルにecho入力するところです。

bash
  tailf -f 入力ファイル | コマンド | read -r res;
  do
   echo 入力文字 >> 入力ファイル  # ⭐️これでコマンドに入力を渡せるんです。
  done

letsencrypt のワイルドカード証明書の更新の場合、上記以外にもフックしなきゃいけない文字列は幾つかあります。すでに証明証発行済みの場合などのためです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0