シェルスクリプトを作成していて、なぜかwhileでループ処理を記載しているのに、1回しか実行されない壁にぶちあたりました。
どうやらsshコマンドを利用していると、そうなるようなので、対処法と合わせて備忘録として残しておきます。
事象
whileでループ処理をさせていて、その中にsshコマンドがあると、1回しか実行されず、ループの2回目以降が実行されない。
例えば、
・複数台のサーバー情報が書かれているCSVファイルを読み込み、
・各サーバーにsshで接続してユーザー一覧をファイル出力
を実行するスクリプトは以下になります。
#!/bin/bash
while read line;do
TARGET_KEY=`echo ${line} |cut -d , -f 1`
TARGET_HOST=`echo ${line} |cut -d , -f 2`
ssh -i ${TARGET_KEY} ${TARGET_HOST} cat /etc/passwd > out.dat
done < list.dat
しかし、上記の実行すると、1回しか出力されません。
原因
sshコマンドを実行すると、ローカルホストからの標準入力を停止し、リモートホストからの標準入力の受付を開始してしまうためです。
そのため、1回目のループでsshを実行したときに、ローカルホストでのファイルの読み込みが停止されてしまっているんですね。
よって、2回目以降のループは実行されず、そのまま実行終了しています。
対処法
sshに 「-n」オプションを付けます。
「-n」オプションを付けることで、標準入力からの読み込みを禁止します。
先ほどのスクリプトを修正すると、以下の通り。※6行目に「-n」オプションを追加。
#!/bin/bash
while read line;do
TARGET_KEY=`echo ${line} |cut -d , -f 1`
TARGET_HOST=`echo ${line} |cut -d , -f 2`
ssh -n -i ${TARGET_KEY} ${TARGET_HOST} cat /etc/passwd > out.dat
done < list.dat
あとがき
はじめは、全然原因がわからず苦戦しました。
1つ1つコメントアウトつけてみてデバッグして、ようやくsshに原因があることがわかりました。
sshコマンドをwhileで処理させるシェルスクリプトは、頻繁に使いそうなので覚えておこう。
コメント