
数週間私を悩ませていた問題をついに解決しました。リモートでコマンドを実行するには、「認証キー」と一緒にSSHを使用します。 whileループでこれを行うときを除いて、すべてが正常です。ループは、sshコマンドを使用した反復後に終了します。
長い間私はこれがkshの奇妙なことだと思いましたが、今ではbashの動作が実際に同じであることがわかりました。
問題を再現する小さなサンプルプログラムです。これは、スナップショットを撮ってクラスタ内のノード間で複製する大規模な実装から抽出されました。
#!/bin/bash
set -x
IDTAG=".*zone"
MARKER="mark-$(date +%Y.%m.%d.%H.%M.%S)"
REMOTE_HOST=sol10-target
ZFSPARENT=rpool
ssh $REMOTE_HOST zfs list -t filesystem -rHo name,mounted $ZFSPARENT | grep "/$IDTAG " > /tmp/actionlist
#for RMT_FILESYSTEM in $(cat /tmp/actionlist)
cat /tmp/actionlist | while read RMT_FILESYSTEM ISMOUNTED
do
echo ${RMT_FILESYSTEM}@${MARKER}
[ "$ISMOUNTED" = "yes" ] && ssh $REMOTE_HOST zfs snapshot -r ${RMT_FILESYSTEM}@${MARKER}
echo Remote Command Return Code: $?
done
(zfs list "-H"オプションの動作定義に応じて、grep検索式にタブ文字があることに注意してください。)
私の例では、ルート用のいくつかのZFSファイルシステムがあります。ここで、すべての「領域」のルートファイルシステムは、次の名前のデータセットにあります。
プール/ゾーン/app1
ゾーンプール/ゾーン/グループ2/app2ゾーン
など。
上記のループは、選択した各データセットのスナップショットを作成するようになっていますが、最初のデータセットでのみ機能してから終了します。
正しい数のデータセットを見つけるプログラムは、スクリプトが存在した後に "/tmp/actionlist"ファイルをチェックすることで簡単に確認できます。
たとえば、ssh コマンドが echo コマンドに変わると、ループはすべての入力ラインを繰り返します。あるいは、私が一番好きなのは、問題のコマンドの前に「echo」を追加することです。
forループを使用すると機能しますが、データセットリストの潜在的なサイズが原因で、最大の拡張コマンドライン長に問題が発生する可能性があります。
これで、sshコマンドを含むループだけが問題を引き起こすと99.999%確信しています!
sshコマンド実行の繰り返しが完了しました!これは、whileループに挿入されたデータが突然消えたのと同じです。入力の最初の数行がsshコマンドを実行しない場合、SSHコマンドが実際に実行されるまでループは続きます。
私がテストしているノートブックには、約2〜3個のサンプルデータセットを含む2つのSolaris 10 VMがあります。ただし、オンラインで接続され、多数のデータセットを持つ大規模なSPARCシステムでも同じことが起こります。
答え1
SSHは標準入力からデータを読み取って作業リストを使い果たすことができます。 SSHの標準入力を/ dev / nullにリダイレクトしてみてください。
ssh $REMOTE_HOST zfs snapshot -r ${RMT_FILESYSTEM}@${MARKER} </dev/null
通常、標準入力を妨げる可能性がある -style ループ内でコマンドを実行するときに、ループ全体の本文を中while read
括弧で囲むのが好きです。
cat /tmp/uuoc | while read RMT_FILESYSTEM ISMOUNTED
do {
echo ${RMT_FILESYSTEM}@${MARKER}
[ "$ISMOUNTED" = "yes" ] && ssh $REMOTE_HOST zfs snapshot -r ${RMT_FILESYSTEM}@${MARKER}
echo Remote Command Return Code: $?
} < /dev/null; done