web-dev-qa-db-ja.com

sshコマンドのタイムアウトを設定し、リモートコマンドの結果を返す方法

何千ものノードに接続し、実行された5つのコマンドの値を返すRHELサーバーでbashで実行されるスクリプトがあります。これは、RHELサーバーからのみ情報を収集します。

正常に動作しますが、問題は、次のコマンドを実行すると一部のノードがフリーズすることです。

rpm -q <package-name>
rpm --queryformat '%{installtime:date} %{name}\n' -q <package-name>

これでスクリプトが確実に停止するので、sshコマンドのタイムアウトを設定し、リモートコマンドが長時間実行されるのを待っている場合(たとえば10秒)、sshセッションを終了します。タイムアウトしてそのsshセッションを終了し、これが発生したら次のノードに移動したいと思います。どうすればよいですか?

これが私が現在情報を引き出してダンプと呼ばれる変数に保存しているスクリプトの部分です[私の貧弱なスクリプトを無視してください、これは新しいです]

dump=$(ssh -o ServerAliveCountMax=1 -o ServerAliveInterval=10 -o ConnectTimeout=10 -o BatchMode=yes $i "cat /proc/meminfo | grep -i \"memtotal\" | cut -d \":\" -f2 | tr -d \" \" | tr -d \"kB\"; cat /etc/redhat-release | cut -d \" \" -f7; dmidecode | grep -i \"prod\" | grep -vi \"desktop\"  | grep -iv \"id\" | cut -d \" \" -f3,4| tr \" \" \"_\" ; uptime | cut -d \" \" -f4,5 | tr \" \" \"_\" | tr -d \",\"; service kdump status 2>/dev/null | tr \" \" \"_\";");

それが長すぎる場合、とにかくこれをタイムアウトすることはありますか?

私がすでに試したこと:

(ssh -q -o Batchmode=yes -o PasswordAuthentication=no -o ConnectTimeout=1 $i "rpm --queryformat '%{installtime:date} %{name}\n' -q \"kexec-tools\" | cut -d \" \" -f1,2,3,4|tr \" \" \"_\"" > /dev/null) & pid=$!
(sleep 10 && kill -HUP $pid ) 2>/dev/null & watcher=$!
if wait $pid 2>/dev/null; then
    pkill -HUP -P $watcher
    wait $watcher
else
    echo -e "$i Unable to ssh" >> res && continue
fi

ただし、この方法では、リモートrpmコマンドの結果を保存できません。

どんな助けでも非常にありがたいです。

3
sidx4

GNU Parallelを使用して、コレクションを並列化します。

parallel --slf rhel-nodes --tag --timeout 1000% --onall --retries 3 \
  "rpm -q {}; rpm --queryformat '%{installtime:date} %{name}\n' -q {}" \
  ::: bash bc Perl

ノードを~/.parallel/rhel-nodesに配置します。

--tagは、出力にノードの名前を付加します。 --timeout 1000%は、コマンドの実行に中央値の10倍の時間がかかると、コマンドが強制終了されることを示しています。 --onallは、すべてのコマンドをすべてのサーバーで実行します。 --retries 3は、失敗した場合、コマンドを最大3回実行します。 ::: bash bc Perlは、テストするパッケージです。パッケージが多数ある場合は、cat packages | parallel ...の代わりにparallel ... ::: packages構文を使用してください。

GNU Parallelは一般的な並列処理機能であり、同じマシン上またはsshアクセスできる複数のマシン上でジョブを簡単に並列実行できます。

4つのCPUで実行する32の異なるジョブがある場合、並列化する簡単な方法は、各CPUで8つのジョブを実行することです。

Simple scheduling

代わりに、GNU Parallelは、終了時に新しいプロセスを生成します。つまり、CPUをアクティブに保ち、時間を節約します。

GNU Parallel scheduling

インストール

GNU Parallelがディストリビューション用にパッケージ化されていない場合は、rootアクセスを必要としない個人インストールを実行できます。これを行うことで10秒で実行できます。

(wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash

その他のインストールオプションについては、 http://git.savannah.gnu.org/cgit/parallel.git/tree/README を参照してください。

詳細

その他の例を参照してください: http://www.gnu.org/software/parallel/man.html

イントロビデオを見る: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

チュートリアルをウォークスルーします: http://www.gnu.org/software/parallel/parallel_tutorial.html

サポートを受けるには、メーリングリストにサインアップしてください: https://lists.gnu.org/mailman/listinfo/parallel

3
Ole Tange

これを解決するためのあなたの試みに感謝します。

私は今問題を解決しました、そして必要な解決はとても単純だったので、私は今かなり愚かだと感じます。

以前に使用したコードでは、

(ssh -q -o Batchmode=yes -o PasswordAuthentication=no -o ConnectTimeout=1 $i "rpm --queryformat '%{installtime:date} %{name}\n' -q \"kexec-tools\" | cut -d \" \" -f1,2,3,4|tr \" \" \"_\"" > /dev/null) & pid=$!

私がする必要があるのは、すべての出力をローカルマシン上のファイルにリダイレクトすることだけでした。それでおしまい。

(ssh -q -o Batchmode=yes -o PasswordAuthentication=no -o ConnectTimeout=1 $i "rpm --queryformat '%{installtime:date} %{name}\n' -q \"kexec-tools\" | cut -d \" \" -f1,2,3,4|tr \" \" \"_\"" > **test**) & pid=$!

私が自分で回答を投稿することにした唯一の理由は、あなたが提供した回答には外部のツール/コードを持ち込んで使用する必要があるためでした。これは私がやりたくないことです。代わりに、パッケージの可用性やOSバージョンに依存せずに適用できるソリューションが必要でした。

それでもありがとう!

1
sidx4