master
リモートコンピュータとSSHセッションを確立し、各リモートコンピュータmaster
で別の内部SSHセッションを確立し、次に2つのコマンドを実行するローカルコンピュータがあります。slaves
つまり、特定のディレクトリを削除して再作成します。
ローカルマシンにはマスター用のパスワードなしのSSHがあり、マスターにはスレーブ用のパスワードなしのSSHがあります。また、.ssh/config
local / masterのすべてのホスト名が知られており、スレーブのホスト名は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 セッションが作成され、かなりの遅延が発生することが確認されました。 SSH接続を減らすために、これら3つのコマンドを1に組み合わせたいと思います。だから最初の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
)を実行してからセッションを終了し、続行します。どうすればいいですか?
答え1
これを考慮して&&
論理演算子だと思います。もちろんいいえ「このコマンドも実行」、「他のコマンドが成功すればこのコマンドを実行」を意味します。
つまり、rm
コマンドが失敗した場合(3つのディレクトリのうちの1つが存在しない場合に発生)、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
Output
とPartition
それを実行する場所があります。
答え2
Jumpboxでいつでも定義できます。OpenSSHの多重化
多重化は、単一の回線または接続を介して複数の信号を送信する機能です。多重化により、OpenSSHは毎回新しい接続を作成するのではなく、複数の同時SSHセッションに対して既存のTCP接続を再利用できます。
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
答え3
すべてのコマンドを「マスター」サーバーの別々のスクリプトに入れることができます。
メインスクリプト
#!/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
答え4
しばらく前に、他の回答が推奨するように制御ソケットを使用する機会がありました(この回答は本質的に制御ソケット使用の組み合わせです)。この回答そしてこのスクリプトこの回答)。
ユースケースはハッキングです。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
実行中のジョブが終了するとすぐに新しいジョブを開始し、サーバー全体にワークロードを分散します。