多くのサーバーでSSH経由でコマンドを自動的に実行する


46

.txtファイルにはIPアドレスのリストがあります。例:

1.1.1.1
2.2.2.2
3.3.3.3

すべてのIPアドレスの背後にサーバーがあり、すべてのサーバーでポート22で実行されているsshdがあります。すべてのサーバーがknown_hostsリストにあるわけではありません(私のPCではUbuntu 10.04 LTS / bash)。

これらのサーバーでコマンドを実行し、出力を収集するにはどうすればよいですか?

理想的には、すべてのサーバーでコマンドを並行して実行したいと思います。

すべてのサーバーで公開鍵認証を使用します。

潜在的な落とし穴を次に示します。

  • sshは、指定されたサーバーのsshキーをknown_hostsファイルに入れるように促します。
  • 指定されたコマンドは、出力が潜在的に無効であることを示すゼロ以外の終了コードを返す場合があります。私はそれを認識する必要があります。
  • たとえば、ネットワークエラーが原因で、特定のサーバーへの接続の確立に失敗する場合があります。
  • コマンドが予想よりも長く実行されたり、コマンドの実行中にサーバーがダウンした場合に備えて、タイムアウトが必要です。

サーバーはAIX / kshです(しかし、私はそれは本当に重要ではないと思います。



1
言及したリンクにはSSHさえ含まれていないため、重複していないと思います。
ランスベインズ

4
まだ行っていない場合は、すべてのマシンでsshサーバーをセットアップし、作業するマシンで秘密/公開キーペアを作成し、公開キーをサーバー上のアカウントにコピーして、パスワードの面倒を防ぎます。それは私の答えにも当てはまり、@ demureにも当てはまります。
アントン

回答:


14

psshなどをインストールできないと仮定すると、次のようなことができます。

tmpdir=${TMPDIR:-/tmp}/pssh.$$
mkdir -p $tmpdir
count=0
while IFS= read -r userhost; do
    ssh -n -o BatchMode=yes ${userhost} 'uname -a' > ${tmpdir}/${userhost} 2>&1 &
    count=`expr $count + 1`
done < userhost.lst
while [ $count -gt 0 ]; do
    wait $pids
    count=`expr $count - 1`
done
echo "Output for hosts are in $tmpdir"

1
このスクリプトで正確に待つのは何ですか?? ty!
ランスベインズ

サーバーキーがknows_hostsファイルにない場合はどうなりますか?
ランスベインズ

5
スクリプトをバックグラウンドに配置すると、子プロセスが作成されます。子プロセスが終了すると、親プロセスが終了するか、親プロセスが子プロセスを「待機」するまで、プロセス「スロット」とリソースがシステムに残ります。これらの「まだ存在するプロセスによって終了」プロセスは、「ゾンビ」プロセスと呼ばれます。子プロセスの後にクリーンアップし、リソースを回収するのは良い動作です。
アルセージュ

1
知られていない場合、それはそれを台無しにするかもしれませんが、-o StrictHostKeyChecking=noこれを避けるために追加することができます。ただし、最初にコマンドラインからすべてのサーバーをスキャンして、ホストキーを追加できるようにすることをお勧めします。
アルケージュ

1
前述したように、sshプログラムがバックグラウンドに置かれ、終了した後もリソースは保持されます。このwaitコマンドは、プロセスのリターンコード(プロセスの終了方法)を含むこれらのリソースを回収します。その後、プログラムの後半で別のプロセスを配置し、バックグラウンドで圧縮を言うと、それを待つ必要がある場合、このループなしで、待機は圧縮ではなく完了したsshプログラムの1つを回収します-走っている 間違った子プロセスの戻りステータスを取得します。自分の後にクリーンアップするのは良いことです。
アルケージュ

61

複数のマシンに同時にログインして一連のコマンドを実行できるツールがいくつかあります。ここにカップルがあります:


1
リストにpdshを追加することもできます。
リッカルドムリ

1
clustershを使用するのはかなり直感的でした。ちょうど私の2セント
...-josinalvo

1
psshを頻繁に使用します。特定のリモートコマンドにはゼロ以外の終了コードがあり、エラーを意味しないことを伝えたいと思いますが、非常にうまく機能します。それは純粋に化粧品です。
アンソニークラーク

1
@AnthonyClarkでは、これらのコマンドに「|| true」のようなものを追加できます。
-exic

16

スクリプトよりもPythonスクリプトの方が 好きならbashFabricがあなたのためのツールかもしれません。

ファブリックホームページ

Fabricは、Python(2.5以降)ライブラリおよびコマンドラインツールであり、アプリケーションの展開またはシステム管理タスクのためのSSHの使用を合理化します。

ローカルまたはリモートシェルコマンド(通常またはsudo経由)を実行し、ファイルをアップロード/ダウンロードするための基本的な一連の操作と、実行中のユーザーに入力を求める、実行を中止するなどの補助機能を提供します。

典型的な使用法には、1つ以上の関数を含むPythonモジュールを作成し、fabコマンドラインツールを介してそれらを実行することが含まれます。


Fabric v1は素晴らしかった。残念ながら、Fabric v2は、このユースケースに役立つ機能のほとんどを削除しました-現在はお勧めしません(2018年6月)。
ミーコヒ

11

そのためにGNUパラレルを使用ています。最も具体的には、このレシピを使用できます。

parallel --tag --nonall --slf your.txt command

your.txtサーバのIPアドレス/名前を持つファイルであること。


私は私の会社のサーバーを使用しておりますのでのみ追加パッケージをインストールするために、私はしたくないのsshを使用して、他の方法がありません
Özzesh

確かに、私は以前にもこれを実行sshしていましたが、他のコンピューターにログインするための何らかの方法と、以前より安全性が低い方法(などrsh)が必要です。マシンからマシンへの移行に使用しているもの(telnet?、rsh?)については説明しません。
アントン

1
@Özzeshはい、コントローラーのみ
Anthon

1
GNUパラレルをインストールしないためのあなたの理由がで覆われている場合Özzeshを参照してください@ oletange.blogspot.dk/2013/04/why-not-install-gnu-parallel.html
オーレ丹下

1
@OleTange誰が私の答えにコメントしたのかがわかりました%-)。このすばらしいソフトウェアをありがとう。
アントン

8

非常に基本的なセットアップ:

for host in $(cat hosts.txt); do ssh "$host" "$command" >"output.$host"; done

名前/パスワードで認証することは、本当に良い考えではありません。これには秘密鍵を設定する必要があります。

ssh-keygen && for host in $(cat hosts.txt); do ssh-copy-id $host; done

1
これは私が探していたものです!!!!! おかげmichas
Özzesh

上記のスクリプトはうまく機能しますが、10台のサーバーで実行した後、スクリプトが応答しません。接続しているsshサーバーからログアウトするにはどうすればよいですか?
Özzesh

明示的にログアウトする必要はありません。この「スクリプト」はssh $host $command、各ホストに対して実行されます。これらのコマンドを手動で実行して、何が起こっているのかを確認してください。
michas


2

psshと、通常のscp、rsyncなどの関連する並列バージョンを探していると思います。


これは削除されるまで1票離れていますが、この後の回答は+10です。完璧な意味
マイケルMrozek

@MichaelMrozekそれはあなたが知っているよりも悪いです。2つのVTDの2番目は、クリックハッピーアクシデントに関するものです。VTDが削除された場合に戻すためにフラグを立てるか、pingを実行するために、このタブを数日間開いています。たぶん、今すぐ反転して投票をクリアすることができます。
カレブ14年

@カレブ修正
マイケル・

2

この種の作業を簡単にするために、Overcastというオープンソースツールを作成しました。

まず、サーバーを定義します。

overcast import vm.01 --ip 1.1.1.1 --ssh-key /path/to/key
overcast import vm.02 --ip 2.2.2.2 --ssh-key /path/to/key

次に、次のように、複数のコマンドとスクリプトファイルを連続して、または並行して実行できます。

overcast run vm.* uptime "free -m" /path/to/script --parallel

2

Hypertableプロジェクトは最近、マルチホストのSSHツールを追加しました。このツールはlibsshと確立接続と問題のコマンドを使用して構築された非同期かつ並列に最大並列処理のために。完全なドキュメントについては、マルチホストSSHツールを参照してください。ホストのセットでコマンドを実行するには、次のように実行します。

$ ht ssh 1.1.1.1,2.2.2.2,3.3.3.3 uptime

たとえば、ホスト名またはIPパターンを指定することもできます。

$ ht ssh 1.1.1.[1-99] uptime
$ ht ssh host[00-99] uptime

また--random-start-delay <millis>、各ホストでコマンドの開始を0〜<millis>ミリ秒のランダムな時間間隔で遅らせるオプションもサポートしています。このオプションを使用すると、実行中のコマンドが中央リソースにアクセスする際の雷鳴の群れの問題を回避できます。


2

collectnodeを開発しました複数のサーバーでタスクを実行するのに非常にシンプルで効果的です(ウィンドウを含む)

CollectNodeの使用方法:

  1. サーバーのリストを作成して、以下を操作します。

    # cat hosts.file
    server1
    server2
    server3
    server4
    server5
    
  2. サーバーのリストを渡すCollectNodeを実行します。

    collectnode --file servers.txt --command='cat /etc/httpd/conf/httpd.conf |grep ^User'
    
  3. 最適には、結果をフィルタリングすることができます。たとえば、このコマンドは、条件が達成されたサーバーのみを表示します。

    collectnode --file servers.txt --command='cat /etc/httpd/conf/httpd.conf |grep ^User' --where="command contain User"
    

https://collectnode.com/5-tasks-collectnode-can-help-managing-servers/


1
CollectNodeの開発者のようです。その場合、回答でそれを開示するか、これは単なるスパムです。
ムル

申し訳ありませんが、それは私の意図ではなく、より具体的になるように修正された回答です。
fvidalmolina

1

本当にすてきな質問のためのヘッドヘッド:

私が見つけた最良の解決策は、それほど驚くべきことではないが、tmuxです。

Ctrl-Bを実行できます。驚くべき結果を得るには、tmuxでsetw synchronize-panesを実行します。このためには、Tmuxの1つのウィンドウの異なるペインで、すべてのssh接続を開いておく必要があります。


0

複数のホストでコマンドを実行するために、おそらくこのようなものが動作しますか?パスワードなしのログイン用に、すべてのホストが.ssh / configにセットアップされているとします。

$ < hosts.txt xargs -I {} ssh {} command


0

ファイル/ etc / sxx / hostsを作成します

次のように入力します:

[grp_ips]
1.1.1.1
2.2.2.2
3.3.3.3

すべてのマシンでsshキーを共有します。

パッケージからsxxをインストールします。

https://github.com/ericcurtin/sxx/releases

次に、次のようなコマンドを実行します。

sxx username@grp_ips "whatever bash command"

出力はどこに書き込まれますか?ゼロ以外の終了ステータスはどのように処理されますか?コメントで返信しないでください。回答を編集して、より明確で完全なものにします。
G-Manは「Reinstate Monica」と言います

0

Paramiko http://www.paramiko.org/およびThread-based parallelism https://docs.python.org/3/library/threading.htmlを使用します。.belowコードを使用すると、各サーバーで複数のコマンドを並行して実行できます。

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.load_system_host_keys()
ssh.connect(hostname, port, username, password)
t = threading.Thread(target=tasks[index], args=(ssh, box_ip,))
t.start()

注:サーバーごとに上記の手順を繰り返します。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.