「シェルスクリプトの基礎 - 入出力」の版間の差分

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動
126行目: 126行目:
|}
|}
</center>
</center>
<br><br>
== expectコマンド ==
expectコマンドを使用すると、任意のコマンドの出力を待ち受けて、自動でそれに対する入力を行うことができる。<br>
例えば、SSHやRsyncのパスワード入力を自動化することができる。<br>
<br>
expectコマンドがインストールされていない場合は、パッケージ管理システム等を使用してインストールする。<br>
<br>
==== expectコマンドの基本 ====
以下の例では、簡単なユーザ入力を必要とするスクリプトを自動で動作させている。<br>
<syntaxhighlight lang="sh">
#!/bin/sh
read -p "Enter your name: " NAME
echo "Hello, $NAME"
</syntaxhighlight>
<br>
これを実行すると、以下のようにユーザ入力の待ち受け状態となる。<br>
Enter your name:
<br>
この状態において、自動的に入力を行うには、以下のように<code>expect -c</code>コマンドを使用する。<br>
以下の例では、外部のシェルスクリプト(Sample.sh)の入力待ちに対して、自動的にMakuという入力を行っている。<br>
<syntaxhighlight lang="python">
#!/bin/sh
expect -c "
    set timeout 3
    spawn ./Sample.sh
    expect \"Enter your name:\"
    send \"Maku\n\"
    interact
"
# 出力
spawn ./Sample.sh
Enter your name: Maku
Hello, Maku
</syntaxhighlight>
<br>
<code>expect -c</code>コマンドのダブルクォーテーションで囲まれた部分には、実行するシェルスクリプトを記述する。<br>
また、この内部でダブルクォーテーションを使用する場合は、<code>\"</code>と記述してエスケープしなければいけないことに注意する。<br>
<br>
expect -cコマンドの内部の各行は、以下のような意味を持っている。<br>
* set timeout 3
*: 外部のシェルスクリプト(Sample.sh)の実行を3秒待つ。
* spawn ./Sample.sh
*: 指定した外部プログラム(./greet.sh)を実行する。
* expect \"Enter your name:\"
*: 外部プログラムの出力(Enter your name:)を待つ。
* send \"Maku\n\"
*: 外部プログラムにMakuと入力して、最後にEnterを入力する。
* interact
*: 外部プログラムとのインタラクションへ戻る。
<br>
==== SSH接続やRsync接続のパスワード入力を自動化する ====
SSHコマンドやRsyncコマンド等のパスワード入力も自動化することができる。<br>
ただし、シェルスクリプト等にパスワードを平文で記述することになるので、ファイルの扱いには十分に注意すること。<br>
<br>
以下の例では、SSHコマンドがパスワード入力を求めてきた時、自動でパスワードを入力してログインしている。<br>
<syntaxhighlight lang="sh">
#!/bin/sh
expect -c "
    set timeout 3
    spawn ssh <ユーザ名>@<ドメイン名またはIPアドレス>
    expect \"password:\"
    send \"<パスワード>\n\"
    interact
"
# 出力
spawn ssh <ユーザ名>@<ドメイン名またはIPアドレス>
<ユーザ名>@<ドメイン名またはIPアドレス>'s password:
Last login: Sat Nov 10 19:58:51 2018 from hogehoge.ap.example.jp
</syntaxhighlight>
<br>
ログイン後に、何らかのコマンド(例 : ls -alF)を実行するところまで自動化するのであれば、<br>
以下のように、プロンプトの$を待ち受けて、次の入力を行えばよい。<br>
<syntaxhighlight lang="sh">
#!/bin/sh
expect -c "
    set timeout 3
    spawn ssh <ユーザ名>@<ドメイン名またはIPアドレス>
    expect \"password:\"
    send \"<パスワード>\n\"
    expect \"$\"
    send \"ls -aFl\n\"
    interact
"
</syntaxhighlight>
<br>
また、Rsyncコマンドでファイル転送する場合も、同様にパスワード入力を自動化できる。<br>
<syntaxhighlight lang="sh">
#!/bin/sh
expect -c "
    spawn rsync -r -h -v --delete public <ユーザ名>@<ドメイン名またはIPアドレス>:public
    expect \"Password:\"
    send \"<パスワード>\n\"
    interact
"
</syntaxhighlight>
<br><br>
<br><br>



2020年11月30日 (月) 02:21時点における版

概要

ここでは、シェルスクリプトでキーボードからの入力を受け付ける方法を記載する。


入力

readコマンドを使用することで、キーボードから入力した内容を変数に格納することができる。

 read 変数名


入力データの表示

以下の例では、キーボードで入力したデータを変数DATAへ格納し、その内容を表示させている。

readコマンドで入力データを読み込んだ後は、そのまま処理が継続する。
これを利用することで、何かキー入力されるまで処理を停止させることができる。

 #!/bin/bash
 
 echo -n "Press any key: "
 read DATA
 echo ""
 echo "Entered key: $DATA"


-pオプションを使用することで、こういう記述方法ができる。

 read -p "表示する文" 変数名


 #!/bin/bash
 
 read -p "Press any key: " DATA
 echo ""
 echo "Entered key: $DATA"


入力データと処理の分岐

caseコマンドと組み合わせることで、入力されたキーの内容によって処理を分岐することができる。

以下では、yキーを入力した場合はOK、nキーを入力した場合はNG、それ以外の場合はPush y or n key.と表示させる。

 #!/bin/bash
 
 read -p "Are you ok ? (y/n): " DATA
 case "$DATA" in
    [yY]) echo "OK" ;;
    [nN]) echo "NG" ;;
    *)    echo "Push y or n key."
 esac


入力データと反復処理

入力した内容によって処理を繰り返したい場合は、whileコマンドと組み合わせる。

以下のシェルスクリプトでは、
Repeat ?(y/n):と表示した後、yキーを入力すると処理を繰り返して、また、Repeat ?(y/n):と表示して入力待ちとなる。
nキーを入力すると、End Repead.と表示してbreakにより繰り返し処理から抜ける。
yキーまたはnキー以外が入力された場合、Input y or n keyと表示して、再度、Repeat ?(y/n):と表示して入力待ちとなる。

 #!/bin/bash
 
 while :
 do
    read -p "Repeat ? (y/n): " DATA
    if [ "$DATA" = "y" ]; then
       echo "Repeat !!"
    elif [ "$DATA" = "n" ]; then
      echo "End repead."
      break
    else
      echo "Input y or n key"
    fi
 done


複数の入力データ

変数を複数用意することで複数の入力を受け付けることができる。

以下のシェルスクリプトでは、変数DATA1、DATA2、DATA3という3つの変数を宣言しているので、
スペース(タブでも可)で区切った3つの値を変数に格納することができる。

 #!/bin/bash
 
 read -p "Press any key: " DATA1 DATA2 DATA3
 echo ""
 echo "Entered key: $DATA1"
 echo "Entered key: $DATA2"
 echo "Entered key: $DATA3"


※区切り文字を変更する場合
区切り文字は、環境変数のIFSを使用することで変更することができる。
以下のシェルスクリプトでは、区切り文字をカンマ(,)に変更して実行している。

 #!/bin/bash
 
 IFS=, read -p "Press any key: " DATA1,DATA2,DATA3
 echo ""
 echo "Entered key: $DATA1"
 echo "Entered key: $DATA2"
 echo "Entered key: $DATA3"


readコマンドのオプション

readコマンドには複数のオプションがあるが、下表によく使用するオプションを記載する。

オプション 説明
-a 変数 入力した値を配列変数に格納する。
-n 文字数 文字数で指定した分だけ読み込む。
キーボードで直接入力すると、2文字を入力した時点で、自動的に入力処理が終了して値が変数に格納される。
また、コピー&ペーストで2文字以上の文字を入力した場合も、指定した分だけが変数に格納される。
-p 文字列 文字列を表示した後、入力待ちになる。
改行文字が入力されると、入力の受け付けが終了する。
-r \(バックスラッシュ)を文字列として変数に格納する。
-s 画面上に入力した文字を表示しない。
-t 秒数 入力待ち時間に制限を付ける。



expectコマンド

expectコマンドを使用すると、任意のコマンドの出力を待ち受けて、自動でそれに対する入力を行うことができる。
例えば、SSHやRsyncのパスワード入力を自動化することができる。

expectコマンドがインストールされていない場合は、パッケージ管理システム等を使用してインストールする。

expectコマンドの基本

以下の例では、簡単なユーザ入力を必要とするスクリプトを自動で動作させている。

 #!/bin/sh
 
 read -p "Enter your name: " NAME
 echo "Hello, $NAME"


これを実行すると、以下のようにユーザ入力の待ち受け状態となる。

Enter your name:


この状態において、自動的に入力を行うには、以下のようにexpect -cコマンドを使用する。
以下の例では、外部のシェルスクリプト(Sample.sh)の入力待ちに対して、自動的にMakuという入力を行っている。

 #!/bin/sh
 
 expect -c "
    set timeout 3
    spawn ./Sample.sh
    expect \"Enter your name:\"
    send \"Maku\n\"
    interact
 "
 
 # 出力
 spawn ./Sample.sh
 Enter your name: Maku
 Hello, Maku


expect -cコマンドのダブルクォーテーションで囲まれた部分には、実行するシェルスクリプトを記述する。
また、この内部でダブルクォーテーションを使用する場合は、\"と記述してエスケープしなければいけないことに注意する。

expect -cコマンドの内部の各行は、以下のような意味を持っている。

  • set timeout 3
    外部のシェルスクリプト(Sample.sh)の実行を3秒待つ。
  • spawn ./Sample.sh
    指定した外部プログラム(./greet.sh)を実行する。
  • expect \"Enter your name:\"
    外部プログラムの出力(Enter your name:)を待つ。
  • send \"Maku\n\"
    外部プログラムにMakuと入力して、最後にEnterを入力する。
  • interact
    外部プログラムとのインタラクションへ戻る。


SSH接続やRsync接続のパスワード入力を自動化する

SSHコマンドやRsyncコマンド等のパスワード入力も自動化することができる。
ただし、シェルスクリプト等にパスワードを平文で記述することになるので、ファイルの扱いには十分に注意すること。

以下の例では、SSHコマンドがパスワード入力を求めてきた時、自動でパスワードを入力してログインしている。

 #!/bin/sh
 
 expect -c "
    set timeout 3
    spawn ssh <ユーザ名>@<ドメイン名またはIPアドレス>
    expect \"password:\"
    send \"<パスワード>\n\"
    interact
 "
 
 # 出力
 spawn ssh <ユーザ名>@<ドメイン名またはIPアドレス>
 <ユーザ名>@<ドメイン名またはIPアドレス>'s password:
 Last login: Sat Nov 10 19:58:51 2018 from hogehoge.ap.example.jp


ログイン後に、何らかのコマンド(例 : ls -alF)を実行するところまで自動化するのであれば、
以下のように、プロンプトの$を待ち受けて、次の入力を行えばよい。

 #!/bin/sh
 
 expect -c "
    set timeout 3
    spawn ssh <ユーザ名>@<ドメイン名またはIPアドレス>
    expect \"password:\"
    send \"<パスワード>\n\"
 
    expect \"$\"
    send \"ls -aFl\n\"
 
    interact
 "


また、Rsyncコマンドでファイル転送する場合も、同様にパスワード入力を自動化できる。

 #!/bin/sh
 
 expect -c "
    spawn rsync -r -h -v --delete public <ユーザ名>@<ドメイン名またはIPアドレス>:public
    expect \"Password:\"
    send \"<パスワード>\n\"
    interact
 "



出力

echoコマンド

echoコマンドで変数の値を出力する時は、以下のように、ダブルクォートで囲む必要がある。

これは、変数展開が行われることによりダブルクォートが取り除かれ、echoコマンドに3つのパラメータが渡されたものとして扱われる。 パラメータの区切りとして使用するスペースの数は関係なく、各パラメータ(AAA、BBB、CCC)が1つのスペースで結合されて出力される。

 # 実行 
 $DATA="AAA   BBB   CCC"
 echo "$DATA"
 
 # 出力
 AAA   BBB   CCC


echoコマンドと文字の色

echoコマンドにおいて、出力内容の色を変更するには、以下のように記述する。

 # 実行
 error()
 {
    echo -e "\033[31m$*\033[00m"
 }
 
 warn()
 {
    echo -e "\033[33m$*\033[00m"
 }
 
 info()
 {
    echo -e "\033[32m$*\033[00m"
 }


# 出力
error 'Error message'
warn 'Warning message'
info 'Information message'