きり丸の技術日記

技術検証したり、資格等をここに残していきます。

【シェル】Expectで特定の文字を検出したら、別のコマンドを打って環境構築を自動化する

参考元の記事が優秀ですので、この記事は「やってみた」レベルの記事になります。詳しいことは参考元記事を参照してください。このコマンドを忘れていたので、私のメモ用記事でもあります。


環境構築時、ディスプレイに「password:」が出力されたら、自動的に用意したパスワードを入力したい。

その願いを叶えてくれるのが「Expect」コマンドです。

なお、多用は厳禁です。「rm -rf」で一斉にファイル削除するように、コマンド自体にインタラクティブな確認を挟ませないオプションがついているはずですので、そちらで対応するのが一般的でしょう。

なんでもできるコマンドだからこそ、どうしても必要なとき以外は使わないようにしましょう。

環境

ユースケース

  • 環境構築
  • 正常起動の監視
    • 30分経過しないと正常終了しないアプリケーション等々の監視
  • 他人が作ったシェルの結果に対して自動化

コマンド例

参考元のQiita記事引用。

#!/bin/sh

PW="Password"

expect -c "
set timeout 5
spawn env LANG=C /usr/bin/ssh hoge@ServerName
expect \"password:\"
send \"${PW}\n\"
expect \"$\"
exit 0
"

実際には違うコマンドを仕様していましたが、分かりづらかったので記事を引用します。

コマンド解説

参考元のQiita記事引用。

コマンド 説明
set timeout デフォルトのタイムアウトする秒数を指定します。指定しない場合は10秒となっています。
expect expectスクリプトで、マシンからの応答を読み取り、パターンマッチをする時に利用します。パターンマッチはswitch文、case文と同様の処理が実現できます。
spawn expect内でプロセスを生成するコマンドです。
send マシンに文字列を返答するコマンドです。
exit expectの処理を終了させ、返り値として指定した数字を返します。

その他の環境構築で便利そうなコマンド

yes


延々とyを出力するだけのコマンド。インストール中に全部Yで入力すればいい場合は、これで解決できる。

なお、yumを例にしているが、yumのオプションで-yがあるのでyumとは組み合わせる必要がない。

yes | yum install XXXXXX
yum -y install XXXXXX

他にもecho yで対策できます。yesで対応できない場合は、こちらで対応するのがいいでしょう。(参考記事参照)

終わりに

分かっていたら非常に便利なコマンドですが、普段使わないので思い出すのに時間がかかってしまいました。知識として機能を知っていたから、このコマンドがあるであろうシェルを片っ端から探して見つけました。

次に同じような環境構築をするときに、このブログにたどり着けることを未来の自分に期待します。


この記事がお役に立ちましたら、各種SNSでのシェアや、今後も情報発信しますのでフォローよろしくお願いします。

参考

敬称略。

ine1127:Linuxの対話がめんどくさい?そんな時こそ自動化だ!-expect編- qiita.com

maku693:Github Actionsでyesコマンドを使いたい時は代わりにecho yするといい maku693.hatenablog.jp

コマンドのインストール。Mac mojaveにはデフォルトで入っていました。

sudo apt-get install -y expect 

備考

用意していたコマンド。

OracleDBのDockerの起動に30分くらいかかるので、Dockerのログを追いつつ「DATABASE IS READY TO USE!」の正常終了メッセージが出力されたら、呼び出し元に完了したことを通知していました。

#!/bin/bash

expect -c "
set timeout 100000
spawn docker logs -f oracle.database
expect \"DATABASE IS READY TO USE!\"
exit 0
"

f:id:nainaistar:20210107220856p:plain

【Java】ドットでSplitしたい時は\\.で区切る

タイトルだけで終わる出落ち記事。
30分引っかかったので、1時間で記事にして残す。

方法

ドット(.)は正規表現特殊文字
ですので、ドットをエスケープする必要がある。

String[] versions = "1.0.10".split("\\.");

本当にやりたかったこと

  1. Gitでmasterにpushした時、Jenkinsを動かす。
  2. すべて正常終了した時に、Jenkinsでパッチバージョンを上げたタグをpushする。

なぜすぐに気付けなかったか

JavaではCheckStyleを入れているので、IDEがサジェスチョンしてくれる。自動変換で目的どおりの正規表現にしてくれます。

ただ、JenkinsはGroovyですので、ローカルに環境構築をしていませんでした。ですので、下記URLで動作確認をしていたが、サジェスチョンは行われないので正しい正規表現を求めるのに時間がかかりました。

https://groovyconsole.appspot.com/


ドットが正規表現特殊文字だということには早期に気付きました。"\."バックスラッシュひとつだけしか付けた場合はSyntax Errorになります。

ただし、当然上記のサイトでは実行前のコンパイルエラーに気付くことはできません。


また、最初にググって出てきたサイトはPatternクラスを使う方式だったので、Jenkinsでのimport方法がよくわからずに地味に混乱しました。

import java.util.regex.Pattern;
Pattern.quote(".")

終わりに

JVMであることを頭に置いて、Javaでやろうと思ったら簡単です。ただ、普段触らないからと言ってJenkinsだから、Groovyだから、と変な先入観があると引っかかってしまいますね。

今後も、変な先入観を考えずに技術に向き合っていきたいです。


この記事がお役に立ちましたら、各種SNSでのシェアや、今後も情報発信しますのでフォローよろしくお願いします。

f:id:nainaistar:20201013111905p:plain

Flyway+Springでデフォルトの接続スキーマを設定ファイルで指定する

複数のスキーマがあるDBに対して、Flyway+Springでアクセスしようとしたときに半日くらい設定に苦労したので、メモとして残しておきます。

環境

設定方法

spring:
  datasource:
    driver-class-name: org.postgresql.Driver
    url: jdbc:postgresql://localhost:5432/postgres
    username: root
    password: root
  flyway:
    schemas: public

何も設定しなかった時の挙動はどうなるか

DatabaseConnectionのDefaultのスキーマに接続します。ですので、PostgreSQLの場合は、DBに設定されたsearch_pathを元に接続スキーマを確認します。

公式引用。

# Comma-separated list of schemas managed by Flyway. These schema names are case-sensitive. If not specified, Flyway uses
# the default schema for the database connection. If <i>flyway.defaultSchema</i> is not specified, then the first of
# this list also acts as default schema.
# Consequences:
# - Flyway will automatically attempt to create all these schemas, unless they already exist.
# - The schemas will be cleaned in the order of this list.
# - If Flyway created them, the schemas themselves will be dropped when cleaning.
# flyway.schemas=

Flyway公式の設定ファイルのURL。 flywaydb.org


PostgreSQLにて、search_pathを調べるSQL

show search_path;

そもそもなぜ時間かかったか

spring.datasourceでスキーマを定義しようとしたため。

SpringではDBへの接続情報はdatasource内に記載するので、Flywayだろうとdatasource内に定義しようとしていました。その結果、PostgreSQL固有のスキーマ指定方法を探す等で遠回りしてしまいました。過去にFlywayを使用せずに、PostgreSQLでのスキーマ指定をして起動する方法を知っていたというところも混乱ポイントです。

また、Dockerで確認がうまくいっていたので、別部署にて払い出されたUserの権限やPassWordが誤っているという方向で調べてしまいました。


ちなみに、Flywayを使わずにPostgreSQLスキーマを指定する場合、次のようにURLにスキーマを付与すると接続できます。

spring:
  datasource:
    driver-class-name: org.postgresql.Driver
    url: jdbc:postgresql://localhost:5432/postgres?currentSchema=test
    username: root
    password: root

教訓

実際の接続先のDBがOracleMySQLPostgreSQLであろうと、Flywayを通じてアクセスする以上はFlyway側に設定をする必要がある。

おそらくこの件に限らず、ライブラリを介在して処理をする場合はライブラリ側の設定を正とする必要がある。

ソースコード

github.com

終わりに

問題の切り分けがうまくできないと、無駄に時間を掛けてしまいますね…。今回の問題に限らずですが。

サクっと切り分けられるようになりたいです。


この記事がお役に立ちましたら、各種SNSでのシェアや、今後も情報発信しますのでフォローよろしくお願いします。

参考

  1. データベースの初期化 spring.pleiades.io

f:id:nainaistar:20201021235115p:plain