SSHセッション内のSSH中の複数のコマンド


10

リモートmasterマシンへのSSHセッションを作成し、次にmasterから各リモートへの別の内部SSHセッションを作成することになっているローカルマシンがありslaves、2つのコマンドを実行して、特定のディレクトリを削除して再作成します。

ローカルマシンにはマスターへのパスワードなしのSSHがあり、マスターにはスレーブへのパスワードなしのSSHがあることに注意してください。また、すべてのホスト名は.ssh/configローカル/マスターマシンで認識されslaves.txtており、スレーブのホスト名はローカルにあり、そこから読み取ります。

だから私がやっていることはこれです:

username="ubuntu"
masterHostname="myMaster"
while read line
do

    #Remove previous folders and create new ones.
    ssh -n $username@$masterHostname "ssh -t -t $username@$line "rm -rf Input Output Partition""
    ssh -n $username@$masterHostname "ssh -t -t $username@$line "mkdir -p EC2_WORKSPACE/$project Input Output Partition""


    #Update changed files...
    ssh -n $username@$masterHostname "ssh -t -t $username@$line "rsync --delete -avzh /EC2_NFS/$project/* EC2_WORKSPACE/$project""

done < slaves.txt 

このクラスターはAmazon EC2上にあり、反復ごとに6つのSSHセッションが作成され、大幅な遅延が発生していることに気付きました。これらの3つのコマンドを1つにまとめて、SSH接続を減らしたいと思います。だから私は最初の2つのコマンドを組み合わせてみました

ssh -n $username@$masterHostname "ssh -t -t $username@$line "rm -rf Input Output Partition && mkdir -p EC2_WORKSPACE/$project Input Output Partition""

しかし、期待どおりに動作しません。最初の実行(rm -rf Input Output Partition)を実行し、セッションを終了して続行するようです。私に何ができる?


3
このような間接的なコマンドの代わりに-J、ジャンプホストを定義するオプションを使用できます。
Hauleth 2017

回答:


15

それ&&が論理演算子であると考えてください。「このコマンドも実行する」という意味ではなく、「他のコマンドが成功した場合にこのコマンドを実行する」という意味です。

つまり、rmコマンドが失敗した場合(3つのディレクトリのいずれかが存在しない場合に発生します)はmkdir実行されません。これは、希望する動作のようには聞こえません。ディレクトリが存在しない場合は、作成してもかまいません。

使用する ;

セミコロン;はコマンドを区切るために使用されます。コマンドは順次実行され、次のコマンドに進む前に各コマンドを待機しますが、コマンドの成功または失敗は互いに影響を及ぼしません。

内部引用符をエスケープする

他の引用符内の引用符はエスケープする必要があります。そうしないと、余分な終点と始点が作成されます。あなたのコマンド:

ssh -n $username@$masterHostname "ssh -t -t $username@$line "rm -rf Input Output Partition && mkdir -p EC2_WORKSPACE/$project Input Output Partition""

になる:

ssh -n $username@$masterHostname "ssh -t -t $username@$line \"rm -rf Input Output Partition && mkdir -p EC2_WORKSPACE/$project Input OutputPartition\""

エスケープされた引用符がないため、現在のコマンドは実行されているはずです。

ssh -n $username@$masterHostname "ssh -t -t $username@$line "rm -rf Input Output Partition

それが成功した場合:

mkdir -p EC2_WORKSPACE/$project Input Output Partition"" # runs on your local machine

ここでは、構文の強調表示によってコマンド全体が赤で表示されています。これは、コマンド全体がsshに渡される文字列であることを意味します。ローカルマシンを確認してください。あなたは、ディレクトリInput OutputPartitionこれを実行していた場所があるかもしれません。


要点を理解しました。混乱した部分の1つはセミコロンでした。これは同時に複数のコマンドを実行するので、使用しなかったためです。
mgus

セミコロンによってコマンドが同時に実行されることはありません。コマンドを実行するためのリファレンスとしてここを参照してください。この&コマンドはバックグラウンドでコマンドを実行します。つまり、次のコマンドに進む前にコマンドが終了するのを待ちません。
Centimane 2017

10

あなたはいつでもOpenSSHの多重化をジャンプボックスで定義することができます

多重化は、単一の回線または接続を介して複数の信号を送信する機能です。多重化により、OpenSSHは、毎回新しいSSHセッションを作成するのではなく、既存のTCP接続を複数の同時SSHセッションに再利用できます。

SSH多重化の利点は、新しいTCP接続を作成するオーバーヘッドがなくなることです。マシンが受け入れることができる接続の総数は有限のリソースであり、その制限は他のマシンよりもいくつかのマシンでより顕著であり、負荷と使用状況の両方に応じて大きく異なります。新しい接続を開くときにも大幅な遅延があります。新しい接続を繰り返し開くアクティビティは、多重化を使用して大幅に高速化できます。

そのためには/etc/ssh/ssh_config

ControlMaster auto
ControlPath ~/.ssh/controlmasters/ssh_mux_%h_%p_%r
ControlPersist 30m

このようにして、次の30分間に同じサーバーに対して行われた連続した接続は、前のssh接続を再利用して行われます。

マシンまたはマシンのグループに定義することもできます。提供されたリンクから取得。

Host machine1
    HostName machine1.example.org
    ControlPath ~/.ssh/controlmasters/%r@%h:%p
    ControlMaster auto
    ControlPersist 10m

それは面白い!特定の接続に対して明示的にオンとオフを切り替える方法はありますか?この1つの使用例では、すべてのSSH接続を大幅に変更するのはやり過ぎのようです。より正確に使用できますか?特定の接続のみの多重化を開始するには?
Centimane 2017

@Centimaneええ、答えが更新されました
Rui F Ribeiro

1
書き込み可能な世界ではなく、ユーザーの自宅にソケットを置くことをお勧めします/tmp/
heemayl 2017

@heemayl良い点。パソコンで編集します。
Rui F Ribeiro 2017

@RuiFRibeiroはまたによると、のように見えるman sshControlPathControlMasterControlPersist渡すための有効なオプションですssh使用して、コマンドを-o。さらに正確な使用例として、最初sshのスクリプトで多重化を設定し、それを他のユーザーのためにリサイクルしますが、それ以外の場合はパフォーマンスの低下を回避できます。「新しい接続を開くときに大幅な遅延もある」ということを考えると、3つのSSH接続ではなくVSを多重化するベンチマークは何でしょうか
Centimane

4

すべてのコマンドを「マスター」サーバー上の別のスクリプトに入れることができます。

マスタースクリプト

#!/bin/bash
rm -rf "Input Output Partition"
mkdir -p "EC2_WORKSPACE/$project Input Output Partition"

次に、sshスクリプトで次のように呼び出します: SSHスクリプト

username="ubuntu"
masterHostname="myMaster"
while read line
do
ssh -n $username@$masterHostname "ssh -t -t $username@$line < /path/to/masterscript.sh"
ssh -n $username@$masterHostname "ssh -t -t $username@$line "rsync --delete -avzh /EC2_NFS/$project/* EC2_WORKSPACE/$project""
done < slaves.txt 

または 、すべてのファイルが最初のマシン上になければならない場合は、次のようにすることができます。

スクリプト1

script2="/path/to/script2"
username="ubuntu"
while read line; do
cat $script2 | ssh -t -t $username@line
done < slaves.txt

スクリプト2

#!/bin/bash
rm -rf "Input Output Partition"
mkdir -p "EC2_WORKSPACE/$project Input Output Partition"
rsync --delete -avzh "/EC2_NFS/$project/* EC2_WORKSPACE/$project"

sshスクリプト

script1="/path/to/script1"
username="ubuntu"
masterHostname="myMaster"
cat $script1 | ssh -n $username@$masterHostname

1

いくつかの時間前、私は他の回答が(この答えは、本質的に同じようコントロールソケットを使用しての組み合わせでお勧めのような制御ソケットを使用する機会だったこの回答などのスクリプトこの回答を)。

ユースケースはハックauthorized_keysでした。ターゲットユーザーのは定期的にスケジュールされたタスクによって定期的に上書きされ、そのファイルに何かを追加するために必要な赤テープを経由せずにすばやくテストしたいと考えました。したがって、必要に応じてそのファイルにキーを追加するwhileループをセットアップし、テストを実行してループをキャンセルします。ただし、スケジュールされたタスクがファイルを上書きする小さなウィンドウがあり、私のループはまだ続きますsleep。したがって、最初に制御ソケットを設定すると、後で問題なくスクリプトをSSHで実行できるようになります。

#! /bin/bash -xe
. "${CONFIG_DIR}/scripts/setup-ssh.sh"

# Build and test
export TEST_LABEL="${_started_by}-${BUILD_TAG%-BUILD*}"
#...
xargs --arg-file test-list \
    --no-run-if-empty \
    --process-slot-var=NUM \
    --max-procs=${#SERVERS[@]} \
    --max-args="${BATCH_SIZE:-20}" \
    "${CONFIG_DIR}/scripts/run-test.sh"

どこにsetup-ssh.shある:

export SSH_CONFIG="${CONFIG_DIR}/scripts/.ssh-config"
mapfile -t SERVERS < "${CONFIG_DIR}/scripts/hosts"

for SERVER in "${SERVERS[@]}"
do
    while ! ssh -F "${SSH_CONFIG}" "${SERVER}" -fnN; do sleep 1; done
    scp -F "${SSH_CONFIG}" "${CONFIG_DIR}/scripts/ssh-script.sh" "${SERVER}":"${TEST_LABEL}.sh"
done

そして.ssh-config

Host test-*
  User test
  StrictHostKeyChecking no
  ControlMaster auto
  ControlPath /tmp/ssh-%h-%p-%r

そしてrun-test.sh

mapfile -t TEST_SERVERS < "${CONFIG_DIR}/scripts/hosts"
ssh -F "${SSH_CONFIG}" "${TEST_SERVERS[$NUM]}" "./${TEST_LABEL}.sh"

シーケンスは次のようになります。

  • メインスクリプト(最初に表示)のソースsetup-ssh.sh
  • setup-ssh.shすべてのサーバーが制御ソケットをセットアップするまでサーバーをビジーループします。hostsファイルには、単にサーバのホスト名を1行につき1つを示しています。
  • 制御ソケットを指定する構成はにのみ存在するため、を使用して${CONFIG_DIR}/scripts/.ssh-configそのファイルを指定しない限り-F、SSH接続はそれを使用しません。したがって、これにより、Fオプションを使用して必要な場所でのみコントロールソケットを使用できます。
  • セットアップスクリプトは、テスト実行スクリプトもサーバーにコピーします。実行スクリプト自体にはたくさんのコマンドが含まれており、実行スクリプトをコピーしたので、SSHの追加のクォーティングレイヤー(および何が拡張されたのかを把握するための追加の認識オーバーヘッド)を心配する必要はありません。
  • 次に、メインスクリプトはxargs、実行中のジョブが終了するとすぐに新しいジョブを開始することにより、サーバーにワークロードを分散するために使用します。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.