Bir SSH oturumunda bir SSH sırasında birden çok komut


10

Uzak bir mastermakineye bir SSH oturumu ve sonra başka bir iç SSH oturumu masteriçin bazı uzaktan her birine slavesve sonra belirli bir dizini silmek ve yeniden oluşturmak için 2 komutları yürütmek gerekiyordu yerel bir makine var.

Yerel makinede master için şifresiz SSH ve master'da slave'lerde şifresiz SSH bulunduğunu unutmayın. Ayrıca tüm ana bilgisayar adları .ssh/configyerel / ana makinelerde bilinir ve kölelerin ana bilgisayar adları slaves.txtyerel olarak bulunur ve onları oradan okurum.

Yani yaptığım ve çalıştığım şey şu:

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 

Bu küme Amazon EC2'de ve her bir yinelemede önemli bir gecikmeye neden olan 6 SSH oturumu oluşturulduğunu fark ettim. Daha az SSH bağlantısı elde etmek için bu 3 komutu 1'de birleştirmek istiyorum. Bu yüzden ilk 2 komutu birleştirmeye çalıştım

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

Ancak beklendiği gibi çalışmaz. İlkini ( rm -rf Input Output Partition) çalıştırıyor gibi görünüyor ve sonra oturumdan çıkıyor ve devam ediyor. Ne yapabilirim?


3
Komutta böyle bir dolaylama yerine -Jatlama ana makinenizi tanımlayacak seçeneği kullanabilirsiniz .
Hauleth

Yanıtlar:


15

Bunun &&mantıklı bir operatör olduğunu düşünün . It does not ortalamaları "de bu komutu çalıştırmak" o "öteki Başarsalardı bu komutu çalıştırmak" anlamına gelir.

Bu, rmkomut başarısız olursa (üç dizinden herhangi biri yoksa gerçekleşir), mkdiryürütülmeyecek demektir. Bu istediğiniz davranış gibi görünmüyor; dizinler mevcut değilse, onları oluşturmak iyi olabilir.

kullanım ;

Noktalı virgül ;, komutları ayırmak için kullanılır. Komutlar sırayla çalıştırılır, bir sonrakine geçmeden önce her birini bekler, ancak başarılarının veya başarısızlıklarının birbirleri üzerinde hiçbir etkisi yoktur.

İç tırnaklardan kaçış

Diğer tırnak içindeki tırnaklardan kaçılmalıdır, aksi takdirde ekstra bir bitiş noktası ve başlangıç ​​noktası oluşturursunuz. Komutunuz:

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

Oluyor:

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

Mevcut komutunuz, kaçan tırnakların olmaması nedeniyle yürütülüyor olmalıdır:

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

başarılı olursa:

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

Sözdizimi vurgulamanın tüm komutu burada kırmızı olarak gösterdiğini göreceksiniz, yani tüm komut ssh'ye geçirilen dizedir. Yerel makinenizi kontrol edin; dizinlere Input Outputve Partitionbunu çalıştırdığınız yere sahip olabilirsiniz .


Puanlarını anlıyorum. Kafamı karıştıran bir kısım noktalı virgüldü, çünkü aynı anda 1'den fazla komut çalıştıracağını düşündüm, bu yüzden kullanmadım.
mgus

Noktalı virgül, komutların aynı anda yürütülmesine neden olmaz, burada komutların yürütülmesi için bir başvuru olarak bakın . &Nedenleri komutları bir sonraki geçmeden önce bitirmek için bekledi alışkanlık araçlar o arka plan, int çalıştırmak için.
Centimane

10

Atlama kutunuzda her zaman OpenSSH'de çoklama tanımlayabilirsiniz

Çoğullama, tek bir hat veya bağlantı üzerinden birden fazla sinyal gönderme yeteneğidir. Çoğullama ile, OpenSSH mevcut TCP bağlantısını her seferinde yeni bir tane oluşturmak yerine birden çok eşzamanlı SSH oturumu için yeniden kullanabilir.

SSH çoğullamasının bir avantajı, yeni TCP bağlantıları oluşturma yükünün ortadan kaldırılmasıdır. Bir makinenin kabul edebileceği toplam bağlantı sayısı sonlu bir kaynaktır ve sınır bazı makinelerde diğerlerine göre daha belirgindir ve hem yüke hem de kullanıma bağlı olarak büyük ölçüde değişir. Yeni bir bağlantı açılırken de önemli bir gecikme olur. Tekrar tekrar yeni bağlantılar açan etkinlikler, çoğullama kullanılarak önemli ölçüde hızlandırılabilir.

Bunun için /etc/ssh/ssh_config:

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

Bu şekilde, takip eden 30 dakika içinde aynı sunucuya arka arkaya yapılan bağlantılar önceki ssh bağlantısı yeniden kullanılarak yapılacaktır.

Ayrıca bir makine veya makine grubu için de tanımlayabilirsiniz. Sağlanan bağlantıdan alınmıştır.

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

İlginç! Belirli bir bağlantı için açıkça açıp kapatmanın bir yolu var mı? Bu tek kullanımlık durum için tüm SSH bağlantılarını büyük ölçüde değiştirmek için aşırı doldurma gibi görünüyor. Daha hassas bir şekilde kullanılabilir mi? Sadece belirli bir bağlantıyı çoğullamaya başlamak için?
Centimane

@Centimane evet, cevabı güncelledi
Rui F Ribeiro

1
Soketi okunabilir bir dünya yerine kullanıcının evine koymanızı öneririm /tmp/.
heemayl

@heemayl İyi bir nokta. Bilgisayardayken düzenleyeceğim.
Rui F Ribeiro

@RuiFRibeiro Ayrıca göre benziyor man ssh, ControlPath, ControlMasterve ControlPersistbir geçmek geçerli tercihler sshkullanılarak komutu -o. Daha da hassas bir kullanım durumu olabilir, sshkomut dosyasının ilkinde çoğullamayı ayarlayın ve diğerleri için geri dönüştürün, aksi takdirde performans cezasından kaçının. "Yeni bir bağlantı açarken de önemli bir gecikme var" göz önüne alındığında VS'nin 3 SSH bağlantısı için değil, çoğullama ölçütünün ne olduğunu merak ediyorum
Centimane

4

Tüm komutlarınızı "ana" sunucunuzdaki ayrı bir komut dosyasına koyabilirsiniz.

Ana Komut Dosyası

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

Sonra ssh betiğinizde şöyle deyin: SSH Script

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 

VEYA tüm dosyaların ilk makinede olması gerekiyorsa, böyle bir şey yapabilirsiniz:

script1

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

script2

#!/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 betiği

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

1

Bir süre önce, diğer cevapların önerdiği gibi kontrol soketlerini kullanma fırsatım vardı (bu cevap aslında bu cevap gibi kontrol soketlerini ve bu cevap gibi komut dosyalarını kullanmanın bir kombinasyonudur ).

Kullanım durumu bir hackti: authorized_keysHedef kullanıcının zamanlanmış bir görev tarafından periyodik olarak üzerine yazılmıştır ve bu dosyaya bir şey eklemek için gereken bürokrasiyi geçmeden işleri hızlı bir şekilde test etmek istedim. Bu yüzden anahtarı o dosyaya gerektiği gibi ekleyen bir test döngüsü kuracağım, testimi çalıştıracağım ve döngüyü iptal edeceğim. Ancak, zamanlanan görevin dosyanın üzerine yazacağı ve döngümün devam edeceği küçük bir pencere olurdu sleep. Bu nedenle, başlangıçta bir kontrol soketi kurmak, komut dosyası SSH'mın daha sonra sorunsuz olmasını sağlar:

#! /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"

Nerede 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

Ve .ssh-config:

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

Ve run-test.sh:

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

Dizi şu şekilde gider:

  • Ana komut dosyası (ilk gösterilen) kaynakları setup-ssh.sh.
  • setup-ssh.shmeşgul, hepsinde bir kontrol soketi kurulumu olana kadar sunucuları döngüler. hostsDosya yalnızca satır başına sunucu ana bilgisayar adlarını birini listeler.
  • Kontrol soketini belirten yapılandırma yalnızca içinde olduğundan ${CONFIG_DIR}/scripts/.ssh-config, bu dosyayı kullanarak belirtmediğim sürece -FSSH bağlantıları bunu kullanmaz. Bu, kontrol soketini sadece Fseçeneği kullanarak ihtiyacım olan yerde kullanmama izin veriyor .
  • Kurulum betiği sınama yürütme betiğini de sunuculara kopyalar. Yürütme komut dosyasının kendisi bir sürü komut içerir ve yürütme komut dosyasını kopyaladığım için, SSH için ek bir katman katmanı (ve ne zaman genişletildiğini anlamak için ek bilişsel yük) hakkında endişelenmem gerekmez.
  • Daha sonra ana komut dosyası xargs, iş yükü biter bitmez yeni işler başlatarak iş yükünü sunucular üzerinde dağıtmak için kullanır .
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.