Komutları SSH üzerinden birçok sunucuda otomatik olarak çalıştır


46

Bir .txt dosyasında IP adreslerinin bir listesi var, örneğin:

1.1.1.1
2.2.2.2
3.3.3.3

Her IP adresinin arkasında bir sunucu var ve her sunucuda 22 numaralı bağlantı noktasında çalışan bir sshd var. known_hostsListede her sunucu yok (bilgisayarımda, Ubuntu 10.04 LTS / bash).

Bu sunucularda komutları nasıl çalıştırabilirim ve çıktıları nasıl toplayabilirim?

İdeal olarak, komutları tüm sunucularda paralel olarak çalıştırmak istiyorum.

Tüm sunucularda ortak anahtar kimlik doğrulaması kullanacağım.

İşte bazı potansiyel tuzaklar:

  • Ssh, bana verilen sunucuları ssh anahtarını dosyama koymamı ister known_hosts.
  • Verilen komutlar, çıkışın potansiyel olarak geçersiz olduğunu belirten sıfır olmayan bir çıkış kodu verebilir. Bunu tanımaya ihtiyacım var.
  • Örneğin bir ağ hatası nedeniyle belirli bir sunucuya bağlantı kurulamayabilir.
  • Komutun beklenenden daha uzun sürmesi durumunda veya komut çalıştırılırken sunucu kapanırsa bir zaman aşımı süresi olmalıdır.

Sunucular AIX / ksh (ancak bunun gerçekten önemli olmadığını düşünüyorum.



1
Bunun bir kopya olmadığını düşünüyorum, çünkü bahsettiğiniz bağlantı SSH bile içermiyor.
LanceBaynes

4
Bunu yapmadıysanız, tüm makinelere ssh sunucuları ayarlamanız, çalıştığınız makinede özel / ortak bir anahtar çifti oluşturmanız ve daha fazla parola sorununu önlemek için ortak anahtarı sunucudaki hesaplara kopyalamanız gerekir. Bu benim cevabım için ve @ yıkım için de geçerlidir.
Anthon

Yanıtlar:


14

Pssh veya başkalarını yükleyemediğinizi varsayarsak, aşağıdakine benzer bir şey yapabilirsiniz:

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"

1
tam olarak bu komut dosyasında ne bekliyor? ty!
LanceBaynes,

Bir sunucu anahtarı benim know_hosts dosyamda değilse ne olur?
LanceBaynes,

5
komut dosyalarını arka plana koymak çocuk işlemlerini yaratır. Bir çocuk süreci çıktığında, 'yuva' ve kaynaklar ana sistemden çıkana veya ana işlem çocuk için 'bekler' kadar sistemde kalır. Bunlara 'halen var olan' sonlanan 'süreçler' zombi 'süreçleri denir. Çocuk işlemlerinden sonra temizlemek ve kaynakları geri almak iyi bir davranış olacaktır.
Arcege

1
Eğer bilinmiyorsa, o zaman bunu mahvedebilir, ancak bundan -o StrictHostKeyChecking=nokaçınmak için ekleyebilirsiniz . Ancak, tüm sunucuları ilk önce bir komut satırından taramak daha iyidir, böylece ana bilgisayar anahtarları eklenebilir.
Arcege

1
Bahsettiğim gibi, ssh programı arkaplana konulduktan ve çıkar çıktıktan sonra, kaynaklar hala korunuyor. waitKomutu (PROSESİ çıkıldı nasıl) işlem dönüş kodu dahil bu kaynakları, reclaims. O zaman programın ilerleyen saatlerinde başka bir işlem koyarsanız, arka planda bir sıkıştırma diyelim ve bunu beklemeniz gerekiyor, o zaman bu döngü olmadan beklemeniz tamamlanan ssh programlarından birini geri alacaktır. koşuyor ol. Yanlış çocuk işleminde geri dönüş durumu elde edersiniz. Kendinizden sonra temizlemek iyidir.
Arcege

61

Aynı anda birden fazla makinede oturum açmanıza ve bir dizi komut çalıştırmanıza olanak sağlayan birkaç araç vardır. İşte bir çift:


1
Listeye pdsh eklemek isteyebilirsiniz .
Riccardo Murri

1
Kümeleri kullanmak için oldukça sezgisel buldum. Sadece benim 2 kuruş ...
josinalvo

1
Sık sık pssh kullanıyorum. Çok iyi çalışır, ancak bazı uzak komutların sıfır olmayan bir çıkış koduna sahip olacağını söyleyebilmeyi isterdim ve bu bir hata anlamına gelmez. Bu tamamen kozmetik olsa da.
Anthony Clark

1
@AnthonyClark, bu komutlara "|| true" gibi bir şey ekleyebilirsiniz.
exic

16

Eğer içine iseniz Python fazla komut dosyası bashkomut dosyası, daha sonra Kumaş sizin için araç olabilir.

Gönderen Kumaş ana sayfasına :

Fabric, uygulama dağıtımı veya sistem yönetimi görevleri için SSH kullanımını kolaylaştırmak için bir Python (2.5 veya daha yüksek) bir kütüphane ve komut satırı aracıdır.

Yerel veya uzak kabuk komutlarını (normalde veya sudo aracılığıyla) yürütmek ve dosya yüklemek / indirmek için çalışan bir kullanıcının giriş yapmasını istemek veya yürütmeyi iptal etmek gibi yardımcı işlevler için temel bir işlem paketi sağlar.

Tipik kullanım, bir veya daha fazla işlev içeren bir Python modülü oluşturmayı ve bunları fab komut satırı aracıyla çalıştırmayı içerir.


Kumaş v1 şaşırtıcıydı. Ne yazık ki, Fabric v2 bu kullanım durumu için faydalı kılan özelliklerin çoğunu kaldırdı - şu anda tavsiye etmem (Haziran 2018).
Meekohi

11

Bunun için GNU paralel kullanıyorum , özellikle de bu tarifi kullanabilirsiniz :

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

your.txtSunucunun IP adresi / isimleri ile birlikte olması.


sadece ssh kullanarak başka yol yok mu? Şirket sunucularını kullandığımdan beri ek paketler yüklemek istemiyorum
Özzesh

Tabii, daha önce de sshvarlığımdan önce bunu yapardım , fakat diğer bilgisayarlara giriş yapmak için biraz bir yol kullanmanız gerekiyordu rsh. Makineden makineye almak için şu anda ne kullandığınızı tanımlamıyorsunuz ( telnet?, rsh?).
Anthon

1
@ Özzesh evet sadece kontrolörde
Anthon

1
Özzesh See @ GNU Paralel yüklemeden değil nedeniniz üzerinde kaplıdır eğer oletange.blogspot.dk/2013/04/why-not-install-gnu-parallel.html
Ole Tange

1
@OleTange Sadece cevabımı yorum yapan kim yaptı% -). Bu mükemmel yazılım parçası için teşekkürler.
Anthon

8

Çok temel kurulum:

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

İsim / şifre ile kimlik doğrulaması gerçekten iyi bir fikir değildir. Bunun için özel bir anahtar oluşturmanız gerekir:

ssh-keygen && for host in $(cat hosts.txt); do ssh-copy-id $host; done

1
aradığım kişi bu !!!!! Teşekkürler michas
Özzesh

Yukarıdaki script benim için iyi çalışıyor ancak 10 serverda çalıştırdıktan sonra script cevap vermiyor. Bağlı olduğum ssh sunucusundan nasıl çıkış yapabilirim?
Özzesh

Net bir şekilde çıkış yapmanız gerekmez. Bu "script" sadece ssh $host $commandher ana bilgisayar için çalışacaktır . Neler olup bittiğini öğrenmek için bu komutları manuel olarak çalıştırmayı deneyin.
Michas


2

Bence pssh ve normal scp, rsync, vb.


Bu, silinmekten bir oy uzakta, ancak bu cevap daha sonra +10'da. Kusursuz bir anlam ifade ediyor
Michael Mrozek

@MichaelMrozek Bildiğinizden daha kötü. İki VTD'den ikincisi, mutlu bir kazada benimdir. Bu sekmeyi birkaç gün boyunca açık tuttum veya silinirse VTD'mi geri almak için işaretleyeceğim. Belki de oyları silmek için şimdi çevirebilirsin.
Caleb

@Caleb Fixed
Michael

2

Bu tür şeyleri kolaylaştırmak için Overcast adlı bir açık kaynaklı araç geliştirdim .

İlk önce sunucularınızı tanımlarsınız:

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

Daha sonra sırayla veya paralel olarak birden çok komut ve komut dosyası çalıştırabilirsiniz:

overcast run vm.* uptime "free -m" /path/to/script --parallel

2

Hypertable proje yakın zamanda çoklu sunucu ssh aracını ekledi. Bu araç libssh ile oluşturulmuştur ve maksimum paralellik için asenkron ve paralel olarak bağlantılar kurar ve komutları verir . Belgelendirme için bkz. Multi-Host SSH Aracı . Bir dizi ana makineye komut çalıştırmak için, aşağıdaki şekilde çalıştırmalısınız:

$ ht ssh 1.1.1.1,2.2.2.2,3.3.3.3 uptime

Örneğin bir ana bilgisayar adı veya IP modeli de belirleyebilirsiniz:

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

Ayrıca --random-start-delay <millis>, her ana bilgisayardaki komutun başlatılmasını 0 ile <millis>milisaniye arasında rastgele bir zaman aralığıyla geciktirecek bir seçeneği de destekler . Bu seçenek, çalıştırılmakta olan komut merkezi bir kaynağa eriştiğinde sürü problemlerini önlemek için kullanılabilir.


2

Collectnode'u geliştirdim Birkaç sunucuda görevlerin yerine getirilmesi için çok basit ve etkili (pencereler dahil)

CollectNode nasıl kullanılır:

  1. Şununla çalışmak için sunucu listesini oluşturun:

    # cat hosts.file
    server1
    server2
    server3
    server4
    server5
    
  2. Servis listesini geçen CollectNode'u yürütün:

    collectnode --file servers.txt --command='cat /etc/httpd/conf/httpd.conf |grep ^User'
    
  3. Sonuç olarak, sonuçları filtrelemek mümkündür, örneğin bu komut yalnızca koşulun yerine getirildiği sunucuyu görüntüler.

    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/


1
CollectNode’un geliştiricisi sizsiniz. Bu durumda, cevabında veya bu sadece spam olduğunu açıklamalısınız.
muru

üzgünüm, niyetim bu değildi, cevap daha spesifik olacak şekilde değiştirildi.
fvidalmolina

1

Gerçekten güzel bir soru için sadece bir destek:

Bulduğum en iyi çözüm, şaşırtıcı olmayan bir şekilde, tmux.

Yapabilirsiniz Ctrl-B: setw synchronize-panes tmux'da muhteşem resut için. Bunun için tüm ssh bağlantılarınızı, 1 pencere Tmux bölmesinden açmış olmalısınız.


0

Belki böyle bir şey çalışır, birden fazla ana bilgisayarda komut çalıştırmak için? tüm ana bilgisayarların parola olmadan oturum açmak için .ssh / config içinde olduklarını varsayalım.

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


0

Bir dosya / etc / sxx / hosts dosyası oluşturun

şöyle doldur:

[grp_ips]
1.1.1.1
2.2.2.2
3.3.3.3

Tüm makinelerde ssh anahtarını paylaşın.

Paketten sxx'i kurun:

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

Ardından komutu şöyle çalıştırın:

sxx username@grp_ips "whatever bash command"

Çıktı nerede yazılı? Sıfır olmayan çıkış durumları nasıl kullanılır? Lütfen yorumlara cevap vermeyin; cevabınızı daha net ve daha eksiksiz hale getirmek için düzenleyin .
G-Man '23:38' de Monica

0

Paramiko http://www.paramiko.org/ ve Thread-based parallelism https://docs.python.org/3/library/threading.html .below kodunu kullanın, her sunucuda paralel olarak birden fazla komut çalıştırmanıza izin verin!

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

Not: Her sunucu için yukarıdaki talimatları tekrarlayın.


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.