while read の中で rsh を実行するとループが止まってしまう件

kshでwhile readを使って1行ずつ処理するプログラムを書いていて,その中でrshコマンドを実行するとその時点でループが止まってしまうという謎の事象に遭遇した.はじめはどこか別のところにバグがあるんだろうと思ってコードを削ってみたり,テストコードを書いてみたり,デバッグしてみたりしたが,最終的にはwhile readの骨組みしか残らなくなって(笑),rshを外すとちゃんとループが回ることともわかったので,何やらrshが悪さしてるんじゃないかみたいなところまで特定することができた.

そこで"sh while read rsh"でググってみたところ,同じ事象がじゃんじゃん出てくるわで,なんだ同じところで悩んでる人たくさんいるじゃないかってちょっと安心した.ということで,せっかくなのでまとめておく.ちなみに今回の動作言語はkshだけど,bashでもその他の類似シェルスクリプトでもきっと一緒なはず.あと今回のコマンドはrshだけど,sshでも同じらしい.

簡単な動作解説

まず動作以下のようなconfファイルを用意して,その中に実行するコマンドを書いておく.

./cmd_list.conf(ダメな例)

CMD1
rsh node1 CMD2
CMD3

このconfファイルをwhile readで1行ずつ回しながら実行していくシェルが以下.${CMD}で実行されるのが期待値だけど,2行目のrshを実行したところでループが終了してしまう.

./cmd_exec.ksh

#!/bin/ksh
while read CMD;
do
 # リストに定義したコマンドを実行する
 ${CMD}
done < ./cmd_list.conf

実行対象(コマンド実行)
CMD1
rsh node1 CMD2

そこでコマンドを実行せずに標準出力してみると,正常に動作するので,何やらrshが悪さしてるんじゃないかみたいな.

./cmd_exec.ksh

#!/bin/ksh
while read CMD;
do
 # リストに定義したコマンドを標準出力する
 print ${CMD}
done < ./cmd_list.conf

実行対象(標準出力のみ)
CMD1
rsh node1 CMD2
CMD3

原因はrshで,rshに-nオプションを付けて標準入力をリダイレクトしないようにしてあげることで,問題は解決する.以下のようにconfファイルを修正して完了.お疲れ様でした.

./cmd_list.conf(正しい例)

CMD1
rsh node1 -n CMD2
CMD3