Secara otomatis menjalankan perintah melalui SSH pada banyak server

46

Ada daftar alamat IP dalam file .txt, mis .:

1.1.1.1
2.2.2.2
3.3.3.3

Di belakang setiap alamat IP ada server, dan pada setiap server ada sshd yang berjalan pada port 22. Tidak setiap server ada dalam known_hostsdaftar (pada PC saya, Ubuntu 10,04 LTS / bash).

Bagaimana saya bisa menjalankan perintah di server ini, dan mengumpulkan output?

Idealnya, saya ingin menjalankan perintah secara paralel di semua server.

Saya akan menggunakan otentikasi kunci publik di semua server.

Berikut adalah beberapa jebakan potensial:

  • Ssh meminta saya untuk memasukkan kunci ssh server yang diberikan ke known_hostsfile saya .
  • Perintah yang diberikan mungkin mengembalikan kode keluar bukan nol, yang menunjukkan bahwa output berpotensi tidak valid. Saya perlu mengenali itu.
  • Sambungan mungkin gagal dibuat ke server yang diberikan, misalnya karena kesalahan jaringan.
  • Harus ada batas waktu, jika perintah berjalan lebih lama dari yang diharapkan atau server turun saat menjalankan perintah.

Servernya AIX / ksh (tapi saya pikir itu tidak masalah.

LanceBaynes
sumber
1
Saya pikir itu bukan duplikat, karena tautan yang Anda sebutkan bahkan tidak mengandung SSH.
LanceBaynes
4
Jika Anda belum melakukannya, Anda harus mengatur server ssh di semua mesin, membuat pasangan kunci privat / publik pada mesin tempat Anda bekerja dan menyalin kunci publik ke akun di server untuk mencegah kerepotan kata sandi lebih lanjut. Itu berlaku untuk jawaban saya, dan untuk @ demure juga.
Anthon

Jawaban:

14

Dengan asumsi bahwa Anda tidak dapat menginstal pssh atau orang lain, Anda dapat melakukan sesuatu yang mirip dengan:

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"
Arcege
sumber
1
apa yang sebenarnya harus dilakukan di skrip ini ?? ty!
LanceBaynes
apa yang terjadi jika kunci server tidak ada dalam file know_hosts saya?
LanceBaynes
5
menempatkan skrip ke latar belakang menciptakan proses anak. Ketika proses anak keluar, proses 'slot' dan sumber daya tetap berada dalam sistem sampai proses induk keluar atau proses induk 'menunggu' untuk anak. Proses-proses 'dihentikan oleh masih ada' ini disebut proses 'zombie'. Merupakan perilaku yang baik untuk membersihkan setelah anak memproses dan mendapatkan kembali sumber daya.
Arcege
1
Jika tidak diketahui, maka itu mungkin mengacaukannya, tetapi Anda dapat menambahkan -o StrictHostKeyChecking=nountuk menghindari ini. Namun lebih baik untuk memindai semua server dari baris perintah terlebih dahulu sehingga kunci host dapat ditambahkan.
Arcege
1
Seperti yang saya sebutkan, setelah program ssh diletakkan di latar belakang dan setelah keluar, sumber daya masih disimpan. The waitperintah mengambil kembali sumber daya tersebut, termasuk kode proses kembali (bagaimana proses-proses yang keluar). Kemudian jika nanti dalam program, Anda meletakkan proses lain, katakanlah kompresi, di latar belakang dan perlu menunggu untuk itu, maka tanpa loop ini, menunggu akan mendapatkan kembali salah satu program ssh yang selesai, bukan kompresi - yang mungkin masih sedang berlari. Anda akan mendapatkan status pengembalian pada proses anak yang salah. Adalah baik untuk membersihkan setelah dirimu sendiri.
Arcege
61

Ada beberapa alat di luar sana yang memungkinkan Anda untuk masuk dan menjalankan serangkaian perintah pada banyak mesin secara bersamaan. Berikut adalah pasangannya:

Caleb
sumber
1
Anda mungkin ingin menambahkan pdsh ke daftar.
Riccardo Murri
1
Saya menemukan clusterssh cukup intuitif untuk digunakan. Hanya 2 sen saya ...
josinalvo
1
Saya sering menggunakan pssh. Ini bekerja dengan sangat baik, walaupun saya berharap saya bisa mengatakannya bahwa perintah remote tertentu akan memiliki kode keluar non-nol, dan itu tidak berarti kesalahan. Itu murni kosmetik sekalipun.
Anthony Clark
1
@AnthonyClark Anda bisa menambahkan sesuatu seperti "|| true" ke perintah-perintah itu.
exic
16

Jika Anda menyukai Python scripting lebih dari bashscripting, maka Fabric mungkin menjadi alat untuk Anda.

Dari halaman beranda Fabric :

Fabric adalah pustaka Python (2.5 atau lebih tinggi) dan alat baris perintah untuk merampingkan penggunaan SSH untuk penerapan aplikasi atau tugas administrasi sistem.

Ini menyediakan rangkaian dasar operasi untuk menjalankan perintah shell lokal atau jarak jauh (biasanya atau melalui sudo) dan mengunggah / mengunduh file, serta fungsi tambahan seperti mendorong pengguna yang sedang berjalan untuk input, atau membatalkan eksekusi.

Penggunaan umum melibatkan pembuatan modul Python yang berisi satu atau lebih fungsi, kemudian menjalankannya melalui alat baris perintah fab.

Riccardo Murri
sumber
Fabric v1 sangat mengagumkan. Sayangnya, Fabric v2 menghapus sebagian besar fitur yang membuatnya berguna untuk kasus penggunaan ini - tidak akan merekomendasikan saat ini (Juni 2018).
Meekohi
11

Saya memang menggunakan GNU parallel untuk itu, paling khusus Anda bisa menggunakan resep ini :

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

Dengan your.txtmenjadi file dengan alamat IP server / nama.

Anthon
sumber
tidak ada cara lain hanya menggunakan ssh Karena saya menggunakan server perusahaan saya, saya tidak ingin menginstal paket tambahan
Özzesh
Tentu, saya pernah melakukan ini sebelum sshada juga, tetapi Anda perlu beberapa cara untuk login ke komputer lain dan cara-cara yang dulu kurang aman (seperti rsh). Anda tidak menggambarkan apa yang Anda gunakan sekarang untuk berpindah dari satu mesin ke mesin lainnya ( telnet?, rsh?).
Anthon
1
@ Özzesh ya hanya pada controller
Anthon
1
@ Özzesh Lihat apakah alasan Anda untuk tidak menginstal GNU Parallel dicakup di oletange.blogspot.dk/2013/04/why-not-install-gnu-parallel.html
Ole Tange
1
@OleTange Baru sadar yang mengomentari jawaban saya% -). Terima kasih atas perangkat lunak yang luar biasa ini.
Anthon
8

Setup yang sangat dasar:

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

Mengautentikasi dengan nama / kata sandi sebenarnya bukan ide yang bagus. Anda harus mengatur kunci pribadi untuk ini:

ssh-keygen && for host in $(cat hosts.txt); do ssh-copy-id $host; done
michas
sumber
1
ini yang saya cari !!!!! Terima kasih michas
Özzesh
skrip di atas bekerja dengan baik untuk saya tetapi setelah dieksekusi di 10 server skrip tidak merespons. Bagaimana saya bisa keluar dari server ssh yang saya sambungkan?
Özzesh
Anda tidak perlu keluar secara eksplisit. "Script" ini hanya akan berjalan ssh $host $commanduntuk setiap host. Cobalah untuk menjalankan perintah-perintah itu secara manual untuk mencari tahu apa yang sedang terjadi.
michas
4

Saya sarankan Ansible.cc . Ini adalah manajer konfigurasi dan dispatcher perintah.

Tom
sumber
2

Saya pikir Anda sedang mencari pssh dan versi paralel terkait dari scp, rsync, dll.

Uncjamil
sumber
Ini satu suara lagi dari yang dihapus, tetapi jawaban ini nanti adalah di +10. Masuk akal
Michael Mrozek
@MichaelMrozek Ini lebih buruk dari yang Anda tahu. Yang kedua dari kedua VTD adalah milik saya pada klik-bahagia-kecelakaan. Saya sudah membuka tab ini selama beberapa hari yang bermaksud menandai atau mem-ping Anda untuk mengembalikan VTD saya jika terhapus. Mungkin Anda bisa membalikkannya sekarang untuk menghapus suara.
Caleb
@ Caleb Memperbaikinya
Michael Mrozek
2

Saya membangun alat open-source bernama Overcast untuk mempermudah hal ini.

Pertama, Anda menentukan server Anda:

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

Kemudian Anda dapat menjalankan beberapa perintah dan file skrip di atasnya, baik secara berurutan atau paralel, seperti:

overcast run vm.* uptime "free -m" /path/to/script --parallel
Andrew Childs
sumber
2

Proyek Hypertable baru-baru ini menambahkan alat ssh multi-host. Alat ini dibangun dengan libssh dan membuat koneksi dan mengeluarkan perintah secara serempak dan paralel untuk paralelisme maksimum. Lihat Alat SSH Multi-Host untuk dokumentasi lengkap. Untuk menjalankan perintah pada set host, Anda akan menjalankannya sebagai berikut:

$ ht ssh 1.1.1.1,2.2.2.2,3.3.3.3 uptime

Anda juga dapat menentukan nama host atau pola IP, misalnya:

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

Ini juga mendukung --random-start-delay <millis>opsi yang akan menunda dimulainya perintah pada setiap host dengan interval waktu acak antara 0 dan <millis>milidetik. Opsi ini dapat digunakan untuk menghindari masalah kawanan petir ketika perintah yang dijalankan mengakses sumber daya pusat.

Doug judd
sumber
2

Saya telah mengembangkan collectnode Sangat sederhana dan efektif untuk menyelesaikan tugas di beberapa server (termasuk windows)

Cara menggunakan CollectNode:

  1. Buat daftar server, untuk bekerja dengan:

    # cat hosts.file
    server1
    server2
    server3
    server4
    server5
    
  2. Jalankan CollectNode dengan melewati daftar serve:

    collectnode --file servers.txt --command='cat /etc/httpd/conf/httpd.conf |grep ^User'
    
  3. Optinally, dimungkinkan untuk memfilter hasil, misalnya perintah ini hanya menampilkan server di mana kondisi tercapai.

    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/

fvidalmolina
sumber
1
Tampaknya Anda adalah pengembang CollectNode. Dalam hal ini, Anda harus mengungkapkan bahwa dalam jawaban atau ini hanya spam.
muru
maaf, itu bukan maksud saya, jawaban dimodifikasi untuk lebih spesifik.
fvidalmolina
1

Hanya pertanyaan untuk pertanyaan yang sangat bagus:

Solusi terbaik yang saya temukan adalah, tidak terlalu mengejutkan, tmux.

Anda dapat melakukan Ctrl-B: setw sinkronisasi-pane di tmux untuk resut yang luar biasa. Anda harus membuka semua koneksi ssh Anda, dalam panel 1 jendela Tmux yang berbeda untuk ini.

Mikhail Krutov
sumber
0

Mungkin sesuatu seperti ini berfungsi, untuk menjalankan perintah pada beberapa host? misalkan semua host diatur dalam .ssh / config untuk login tanpa kata sandi.

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

Y0NG
sumber
0

Buat file / etc / sxx / hosts

mengisi seperti ini:

[grp_ips]
1.1.1.1
2.2.2.2
3.3.3.3

Bagikan kunci ssh di semua mesin.

Instal sxx dari paket:

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

Kemudian jalankan perintah seperti ini:

sxx username@grp_ips "whatever bash command"
ericcurtin
sumber
Di mana keluaran ditulis? Bagaimana cara menangani status keluar yang tidak nol? Tolong jangan menanggapi dalam komentar; edit jawaban Anda untuk membuatnya lebih jelas dan lebih lengkap.
G-Man Mengatakan 'Reinstate Monica'
0

Gunakan Paramiko http://www.paramiko.org/ dan paralelisme berbasis Thread https://docs.python.org/3/library/threading.html. Kode di bawah ini memungkinkan untuk mengeksekusi beberapa perintah pada setiap server secara paralel!

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()

Catatan: ulangi instruksi di atas untuk setiap server.

Sharma
sumber
0

Saya pikir "berharap" adalah apa yang Anda butuhkan.
Banyak orang bahkan tidak tahu itu ada. Ini adalah program berbasis tcl yang akan membuat pertanyaan dan kemungkinan jawaban atas nama Anda. Lihat https://wiki.tcl-lang.org/page/Expect

Sejuk
sumber