Banyak perintah selama SSH di dalam sesi SSH

10

Saya memiliki mesin lokal yang seharusnya membuat sesi SSH ke mastermesin jarak jauh dan kemudian sesi SSH dalam lainnya dari masterke masing-masing beberapa remote slaves, dan kemudian menjalankan 2 perintah yaitu untuk menghapus direktori tertentu dan membuatnya kembali.

Perhatikan bahwa mesin lokal memiliki SSH tanpa kata sandi untuk master dan master memiliki SSH tanpa kata sandi untuk slave. Juga semua nama host dikenal di .ssh/configmesin lokal / master dan nama host para budak ada di slaves.txtlokal dan saya membacanya dari sana.

Jadi yang saya lakukan dan kerjakan adalah ini:

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 

Cluster ini ada di Amazon EC2 dan saya perhatikan ada 6 sesi SSH yang dibuat pada setiap iterasi yang menyebabkan penundaan yang signifikan. Saya ingin menggabungkan 3 perintah ini menjadi 1 untuk mendapatkan koneksi SSH yang lebih sedikit. Jadi saya mencoba menggabungkan 2 perintah pertama menjadi

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

Tapi itu tidak berfungsi seperti yang diharapkan. Tampaknya mengeksekusi yang pertama ( rm -rf Input Output Partition) dan kemudian keluar dari sesi dan berlanjut. Apa yang dapat saya?

mgus
sumber
3
Alih-alih tipuan seperti itu dalam perintah Anda dapat menggunakan -Jopsi yang akan menentukan host melompat Anda.
Hauleth

Jawaban:

15

Anggap itu &&operator yang logis. Itu tidak berarti "juga jalankan perintah ini" itu berarti "jalankan perintah ini jika yang lain berhasil".

Itu berarti jika rmperintah gagal (yang akan terjadi jika salah satu dari tiga direktori tidak ada) maka mkdirtidak akan dieksekusi. Ini tidak terdengar seperti perilaku yang Anda inginkan; jika direktori tidak ada, mungkin baik untuk membuatnya.

Menggunakan ;

Titik koma ;digunakan untuk memisahkan perintah. Perintah dijalankan secara berurutan, menunggu masing-masing sebelum melanjutkan ke yang berikutnya, tetapi keberhasilan atau kegagalan mereka tidak berdampak satu sama lain.

Melarikan diri dari kutipan batin

Kutipan di dalam kutipan lain harus diloloskan, jika tidak, Anda membuat titik akhir dan titik awal tambahan. Perintah Anda:

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

Menjadi:

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

Perintah Anda saat ini, karena kurangnya kutipan yang lolos harus dijalankan:

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

jika itu berhasil:

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

Anda akan melihat highlight sintaks menunjukkan seluruh perintah sebagai merah di sini, yang berarti seluruh perintah adalah string yang diteruskan ke ssh. Periksa mesin lokal Anda; Anda mungkin memiliki direktori Input Outputdan di Partitionmana Anda menjalankan ini.

Centimane
sumber
Saya mengerti poin Anda. Satu bagian yang saya bingung adalah titik koma, karena saya pikir itu akan mengeksekusi lebih dari 1 perintah pada saat yang sama itulah sebabnya saya tidak menggunakannya.
mgus
Tanda titik koma tidak akan menyebabkan perintah dieksekusi pada saat yang sama lihat di sini sebagai referensi untuk mengeksekusi perintah. The &penyebab perintah untuk menjalankan int latar belakang dia, yang berarti mereka wont menunggu sampai akhir sebelum bergerak ke depan.
Centimane
10

Anda selalu dapat mendefinisikan dalam Multiplexing kotak lompatan Anda di OpenSSH

Multiplexing adalah kemampuan untuk mengirim lebih dari satu sinyal melalui satu saluran atau koneksi. Dengan multiplexing, OpenSSH dapat menggunakan kembali koneksi TCP yang sudah ada untuk beberapa sesi SSH bersamaan daripada membuat yang baru setiap kali.

Keuntungan dengan multiplexing SSH adalah bahwa overhead untuk menciptakan koneksi TCP baru dihilangkan. Jumlah keseluruhan koneksi yang dapat diterima mesin adalah sumber daya yang terbatas dan batasnya lebih terlihat pada beberapa mesin daripada yang lain, dan sangat bervariasi tergantung pada beban dan penggunaan. Ada juga penundaan signifikan saat membuka koneksi baru. Aktivitas yang berulang kali membuka koneksi baru dapat dipercepat secara signifikan menggunakan multiplexing.

Untuk itu lakukan di /etc/ssh/ssh_config:

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

Dengan cara ini, setiap koneksi berurutan yang dibuat ke server yang sama dalam 30 menit berikutnya akan dilakukan menggunakan kembali koneksi ssh sebelumnya.

Anda juga dapat mendefinisikannya untuk mesin atau sekelompok mesin. Diambil dari tautan yang disediakan.

Host machine1
    HostName machine1.example.org
    ControlPath ~/.ssh/controlmasters/%r@%h:%p
    ControlMaster auto
    ControlPersist 10m
Rui F Ribeiro
sumber
Itu menarik! Apakah ada cara untuk menyalakan dan mematikannya secara eksplisit untuk koneksi yang diberikan? Sepertinya berlebihan untuk secara drastis mengubah semua koneksi SSH untuk kasus penggunaan yang satu ini. Bisakah itu digunakan dengan cara yang lebih tepat? Untuk memulai multiplexing hanya koneksi tertentu?
Centimane
@Centimane ya, perbarui jawabannya
Rui F Ribeiro
1
Saya akan menyarankan untuk meletakkan soket di rumah pengguna daripada dunia yang bisa dibaca-tulis /tmp/.
heemayl
@ Heemayl Poin yang bagus. Saya akan mengeditnya ketika di komputer.
Rui F Ribeiro
@RuiFRibeiro Juga terlihat seperti, menurut man ssh, ControlPath, ControlMasterdan ControlPersistpilihan yang valid untuk lulus sshperintah dengan menggunakan -o. Bisa menjadi kasus penggunaan yang lebih tepat, mengatur multiplexing di sshskrip pertama dan mendaur ulangnya untuk yang lain, tetapi sebaliknya hindari penalti performa. Saya bertanya-tanya apa tolok ukur multiplexing VS bukan untuk 3 koneksi SSH, mengingat bahwa "Ada juga penundaan yang signifikan ketika membuka koneksi baru"
Centimane
4

Anda dapat menempatkan semua perintah Anda ke skrip terpisah di server "master" Anda.

Master Script

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

Kemudian dalam skrip ssh Anda, panggil seperti ini: 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 

ATAU jika semua file harus pada mesin awal Anda bisa melakukan sesuatu seperti ini:

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"

skrip ssh

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

Beberapa waktu yang lalu, saya memiliki kesempatan untuk menggunakan soket kontrol seperti rekomendasi jawaban lain (jawaban ini pada dasarnya adalah kombinasi dari menggunakan soket kontrol seperti jawaban ini dan skrip seperti jawaban ini ).

Kasus penggunaan adalah hack: Pengguna authorized_keystarget ditimpa secara berkala oleh tugas yang dijadwalkan dan saya ingin dengan cepat menguji sesuatu tanpa melalui birokrasi yang diperlukan untuk menambahkan sesuatu ke file itu. Jadi saya akan menyiapkan loop sementara yang menambahkan kunci ke file itu sesuai kebutuhan, menjalankan tes saya, dan membatalkan loop. Namun, akan ada jendela kecil di mana tugas yang dijadwalkan akan menimpa file dan loop saya akan tetap sleep. Jadi, menyiapkan soket kontrol di awal akan membiarkan skrip SSH saya nanti tanpa masalah:

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

Dimana 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

Dan .ssh-config:

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

Dan run-test.sh:

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

Urutannya seperti ini:

  • Sumber utama skrip (ditunjukkan pertama) setup-ssh.sh.
  • setup-ssh.shsibuk-loop server sampai semuanya memiliki pengaturan soket kontrol. The hostsFile hanya berisi daftar salah satu nama host server yang per baris.
  • Karena konfigurasi yang menentukan soket kontrol hanya ada ${CONFIG_DIR}/scripts/.ssh-config, kecuali saya menentukan file yang digunakan -F, koneksi SSH tidak akan menggunakannya. Jadi ini memungkinkan saya untuk menggunakan soket kontrol hanya di mana saya membutuhkannya menggunakan Fopsi.
  • Skrip pengaturan juga menyalin skrip pelaksanaan pengujian ke server. Script eksekusi itu sendiri berisi banyak perintah, dan karena saya menyalin script eksekusi, saya tidak perlu khawatir tentang lapisan tambahan mengutip untuk SSH (dan overhead kognitif tambahan untuk mencari tahu apa yang akan diperluas ketika).
  • Kemudian skrip utama digunakan xargsuntuk mendistribusikan beban kerja melalui server, dengan memulai pekerjaan baru segera setelah menjalankan yang berakhir.
muru
sumber