เรียกใช้คำสั่งผ่าน SSH บนเซิร์ฟเวอร์หลายเครื่องโดยอัตโนมัติ


46

มีรายการที่อยู่ IP ในไฟล์. txt เช่น:

1.1.1.1
2.2.2.2
3.3.3.3

ที่อยู่ IP ทุกหลังมีเซิร์ฟเวอร์และทุกเซิร์ฟเวอร์มี sshd ที่ทำงานอยู่ที่พอร์ต 22 ไม่ใช่เซิร์ฟเวอร์ทุกเครื่องที่อยู่ในknown_hostsรายการ (บนพีซีของฉัน Ubuntu 10.04 LTS / bash)

ฉันจะรันคำสั่งบนเซิร์ฟเวอร์เหล่านี้และรวบรวมผลลัพธ์ได้อย่างไร

เป็นการดีที่ฉันต้องการเรียกใช้คำสั่งแบบขนานบนเซิร์ฟเวอร์ทั้งหมด

ฉันจะใช้การรับรองความถูกต้องของรหัสสาธารณะในเซิร์ฟเวอร์ทั้งหมด

นี่คือข้อผิดพลาดที่อาจเกิดขึ้น:

  • ssh แจ้งให้ฉันใส่คีย์ ssh ของเซิร์ฟเวอร์ที่ระบุลงในknown_hostsไฟล์ของฉัน
  • คำสั่งที่กำหนดอาจส่งคืนโค้ดการออกที่ไม่ใช่ศูนย์ซึ่งบ่งชี้ว่าเอาต์พุตอาจไม่ถูกต้อง ฉันต้องยอมรับว่า
  • การเชื่อมต่ออาจล้มเหลวในการสร้างไปยังเซิร์ฟเวอร์ที่กำหนดตัวอย่างเช่นเนื่องจากข้อผิดพลาดของเครือข่าย
  • ควรมีการหมดเวลาในกรณีที่คำสั่งรันนานกว่าที่คาดไว้หรือเซิร์ฟเวอร์หยุดทำงานในขณะที่รันคำสั่ง

เซิร์ฟเวอร์คือ AIX / ksh (แต่ฉันคิดว่ามันไม่สำคัญ



1
ฉันคิดว่ามันไม่เหมือนกันเพราะลิงก์ที่คุณพูดถึงไม่ได้มี SSH
LanceBaynes

4
หากคุณยังไม่ได้ดำเนินการคุณควรตั้งค่าเซิร์ฟเวอร์ ssh บนเครื่องทั้งหมดสร้างคู่ส่วนตัว / สาธารณะคีย์บนเครื่องที่คุณทำงานจากนั้นคัดลอกรหัสสาธารณะไปยังบัญชีบนเซิร์ฟเวอร์เพื่อป้องกันการเพิ่มรหัสผ่านยุ่งยาก นั่นใช้สำหรับคำตอบของฉันและสำหรับ @ demure ก็เช่นกัน
Anthon

คำตอบ:


14

สมมติว่าคุณไม่สามารถติดตั้ง pssh หรืออื่น ๆ ได้คุณสามารถทำสิ่งที่คล้ายกับ:

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
สิ่งที่ไม่รอทำในสคริปต์นี้ ?? TY!
LanceBaynes

จะเกิดอะไรขึ้นหากคีย์เซิร์ฟเวอร์ไม่อยู่ในไฟล์ Know_hosts ของฉัน
LanceBaynes

5
การวางสคริปต์ในพื้นหลังจะสร้างกระบวนการลูก เมื่อกระบวนการลูกออกกระบวนการ 'สล็อต' และทรัพยากรจะอยู่ในระบบจนกว่ากระบวนการหลักจะจบการทำงานหรือกระบวนการหลัก 'รอ' สำหรับเด็ก กระบวนการ 'ยุติโดยยังคงอยู่' เหล่านี้เรียกว่ากระบวนการ 'ซอมบี้' เป็นพฤติกรรมที่ดีในการทำความสะอาดหลังจากที่เด็กได้รับการสนับสนุนและเรียกคืนทรัพยากร
Arcege

1
หากไม่ทราบว่าอาจทำให้เกิดเกลียวขึ้น แต่คุณสามารถเพิ่ม-o StrictHostKeyChecking=noเพื่อหลีกเลี่ยงปัญหานี้ได้ อย่างไรก็ตามควรสแกนเซิร์ฟเวอร์ทั้งหมดจากบรรทัดคำสั่งก่อนเพื่อให้สามารถเพิ่มโฮสต์คีย์ได้
Arcege

1
ดังที่ฉันกล่าวถึงหลังจากที่โปรแกรม ssh ถูกใส่เข้าไปในพื้นหลังและหลังจากที่มันออกไปทรัพยากรก็ยังคงอยู่ waitคำสั่ง reclaims ทรัพยากรเหล่านั้นรวมทั้งรหัสกระบวนการผลตอบแทน (วิธี processs ออก) จากนั้นหากหลังจากนั้นในโปรแกรมคุณใส่กระบวนการอื่นให้พูดการบีบอัดในพื้นหลังและต้องรอมันจากนั้นหากไม่มีลูปนี้การรอจะเรียกคืนหนึ่งในโปรแกรม ssh ที่เสร็จสมบูรณ์ไม่ใช่การบีบอัด - ซึ่งอาจยัง จะวิ่ง คุณจะได้รับสถานะการส่งคืนในกระบวนการลูกที่ไม่ถูกต้อง เป็นการดีที่จะทำความสะอาดหลังจากตัวคุณเอง
Arcege

61

มีเครื่องมือหลายอย่างที่ช่วยให้คุณสามารถเข้าสู่ระบบและดำเนินการชุดคำสั่งบนเครื่องหลายเครื่องในเวลาเดียวกัน นี่คือคู่:


1
คุณอาจต้องการเพิ่มpdshลงในรายการ
Riccardo Murri

1
ฉันพบว่ากลุ่มใช้งานง่ายพอสมควร เพียง 2 เซ็นต์ของฉัน ...
josinalvo

1
ฉันใช้ pssh บ่อยๆ มันทำงานได้ดีมากแม้ว่าฉันจะหวังว่าฉันจะบอกได้ว่าคำสั่งระยะไกลบางอย่างจะมีรหัสออกที่ไม่เป็นศูนย์และนั่นก็ไม่ได้หมายความว่ามีข้อผิดพลาด นั่นเป็นเครื่องสำอางแท้ๆ
Anthony Clark

1
@AnthonyClark คุณสามารถต่อท้ายคำสั่งเหล่านั้นเช่น "|| true"
exic

16

หากคุณใช้สคริปต์Pythonมากกว่า bashสคริปต์ดังนั้นFabricอาจเป็นเครื่องมือสำหรับคุณ

จากหน้าแรกของผ้า :

Fabric เป็นไลบรารี Python (2.5 หรือสูงกว่า) และเครื่องมือบรรทัดคำสั่งสำหรับการทำให้การใช้ SSH เป็นไปอย่างราบรื่นสำหรับการปรับใช้แอพพลิเคชั่นหรืองานการบริหารระบบ

มันมีชุดของการดำเนินงานขั้นพื้นฐานสำหรับการดำเนินการคำสั่งเปลือกท้องถิ่นหรือระยะไกล (ปกติหรือผ่าน sudo) และการอัปโหลด / ดาวน์โหลดไฟล์เช่นเดียวกับฟังก์ชั่นเสริมเช่นการแจ้งให้ผู้ใช้ทำงานสำหรับการป้อนข้อมูลหรือยกเลิกการดำเนินการ

การใช้งานทั่วไปเกี่ยวข้องกับการสร้างโมดูล Python ที่มีหนึ่งฟังก์ชันขึ้นไปจากนั้นเรียกใช้งานผ่านเครื่องมือบรรทัดคำสั่ง fab


ผ้า v1 น่าทึ่งมาก น่าเสียดายที่ Fabric v2 ลบคุณลักษณะส่วนใหญ่ที่ทำให้มีประโยชน์สำหรับกรณีการใช้งานนี้ - จะไม่แนะนำในปัจจุบัน (มิถุนายน 2018)
Meekohi

11

ฉันใช้GNU ขนานสำหรับสิ่งนั้นโดยเฉพาะคุณสามารถใช้สูตรนี้ได้มากที่สุด:

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

ด้วยyour.txtการเป็นไฟล์ที่มีที่อยู่ IP / ชื่อเซิร์ฟเวอร์


ไม่มีวิธีอื่นในการใช้ ssh เท่านั้นเนื่องจากฉันใช้เซิร์ฟเวอร์ บริษัท ของฉันฉันไม่ต้องการติดตั้งแพ็กเกจเพิ่มเติม
Özzesh

แน่นอนว่าฉันเคยทำสิ่งนี้มาก่อนsshเช่นกัน แต่คุณต้องการวิธีการเข้าสู่คอมพิวเตอร์เครื่องอื่นและวิธีที่เคยปลอดภัยน้อยกว่า (เช่นrsh) คุณไม่ได้อธิบายสิ่งที่คุณใช้ตอนนี้เพื่อรับจากเครื่องหนึ่งไปยังอีกเครื่องหนึ่ง ( telnet?, rsh?)
Anthon

1
@ Özzeshใช่เฉพาะกับคอนโทรลเลอร์
Anthon

1
@ Özzeshดูว่าเหตุผลของคุณสำหรับการไม่ติดตั้ง GNU Parallel อยู่ในoletange.blogspot.dk/2013/04/why-not-install-gnu-parallel.html หรือไม่
Ole Tange

1
@OleTange เพิ่งรู้ว่าใครแสดงความคิดเห็นกับคำตอบของฉัน% -) ขอบคุณสำหรับซอฟต์แวร์ที่ยอดเยี่ยมชิ้นนี้
Anthon

8

การตั้งค่าพื้นฐานมาก:

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

การรับรองความถูกต้องด้วยชื่อ / รหัสผ่านไม่มีความคิดที่ดี คุณควรตั้งค่าคีย์ส่วนตัวสำหรับสิ่งนี้:

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

1
นี่คือสิ่งที่ฉันกำลังมองหา !!!!! ขอบคุณไมเคิล
Özzesh

สคริปต์ข้างต้นทำงานได้ดีสำหรับฉัน แต่หลังจากทำงานใน 10 เซิร์ฟเวอร์สคริปต์ไม่ตอบสนอง ฉันจะออกจากเซิร์ฟเวอร์ในแบบฟอร์ม ssh ที่ฉันเชื่อมต่อได้อย่างไร
Özzesh

คุณไม่จำเป็นต้องออกจากระบบอย่างชัดเจน "สคริปต์" นี้จะทำงานssh $host $commandสำหรับโฮสต์แต่ละรายการ ลองเรียกใช้คำสั่งเหล่านั้นด้วยตนเองเพื่อค้นหาว่าเกิดอะไรขึ้น
michas

4

ผมขอแนะนำให้Ansible.cc มันเป็นเครื่องมือจัดการการกำหนดค่าและโปรแกรมเลือกจ่ายคำสั่ง


2

ฉันคิดว่าคุณกำลังมองหาpsshและรุ่นขนานที่เกี่ยวข้องของ scp, rsync ฯลฯ


นี่คือหนึ่งคะแนนจากการถูกลบ แต่คำตอบในภายหลังนี้คือ +10 ทำให้รู้สึกที่สมบูรณ์แบบ
Michael Mrozek

@MichaelMrozek มันแย่กว่าที่คุณรู้ วินาทีที่สองของทั้งสอง VTD เป็นของฉันในอุบัติเหตุการคลิกที่มีความสุข ฉันเปิดแท็บนี้ไว้สองสามวันเพื่อตั้งค่าสถานะหรือ ping ให้คุณเปลี่ยน VTD ของฉันกลับคืนถ้ามันถูกลบไป บางทีคุณสามารถพลิกตอนนี้เพื่อล้างคะแนน
คาเลบ

@Caleb แก้ไขมัน
Michael Mrozek

2

ฉันสร้างเครื่องมือโอเพ่นซอร์สที่เรียกว่าOvercastเพื่อทำให้สิ่งนี้ง่ายขึ้น

ก่อนอื่นให้คุณกำหนดเซิร์ฟเวอร์ของคุณ:

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

จากนั้นคุณสามารถเรียกใช้คำสั่งและไฟล์สคริปต์หลายคำสั่งโดยเรียงตามลำดับหรือขนานเช่น:

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

2

Hypertableโครงการเมื่อเร็ว ๆ นี้ได้มีการเพิ่มเครื่องมือ SSH หลายโฮสต์ เครื่องมือนี้สร้างขึ้นด้วย libssh และสร้างคำสั่งการเชื่อมต่อและออกคำสั่งแบบอะซิงโครนัสและขนานเพื่อความขนานสูงสุด ดูMulti-Host SSH Toolสำหรับเอกสารที่สมบูรณ์ ในการรันคำสั่งบนชุดโฮสต์คุณจะต้องรันคำสั่งดังนี้:

$ ht ssh 1.1.1.1,2.2.2.2,3.3.3.3 uptime

คุณยังสามารถระบุชื่อโฮสต์หรือรูปแบบ IP ได้เช่น:

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

นอกจากนี้ยังสนับสนุน--random-start-delay <millis>ตัวเลือกที่จะชะลอการเริ่มต้นของคำสั่งในแต่ละโฮสต์โดยช่วงเวลาแบบสุ่มระหว่าง 0 ถึง<millis>มิลลิวินาที ตัวเลือกนี้สามารถใช้เพื่อหลีกเลี่ยงปัญหาฝูงฟ้าร้องเมื่อคำสั่งถูกเรียกใช้เข้าถึงทรัพยากรกลาง


2

ฉันได้พัฒนาcollectnodeง่ายมากและมีประสิทธิภาพในการเรียกใช้งานในหลาย ๆ เซิร์ฟเวอร์ (รวมอยู่ใน windows)

วิธีใช้ CollectNode:

  1. สร้างรายการเซิร์ฟเวอร์เพื่อทำงานกับ:

    # cat hosts.file
    server1
    server2
    server3
    server4
    server5
    
  2. ดำเนินการ CollectNode ผ่านรายการของบริการ:

    collectnode --file servers.txt --command='cat /etc/httpd/conf/httpd.conf |grep ^User'
    
  3. เป็นไปได้ที่จะกรองผลลัพธ์ตัวอย่างเช่นคำสั่งนี้แสดงเฉพาะเซิร์ฟเวอร์ที่เงื่อนไขสำเร็จ

    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 ในกรณีนี้คุณควรเปิดเผยว่าในคำตอบหรือนี่เป็นเพียงสแปม
muru

ขออภัยนั่นไม่ใช่ความตั้งใจของฉันคำตอบที่ได้รับการแก้ไขให้มีความเฉพาะเจาะจงมากขึ้น
fvidalmolina

1

เพียง Headsup สำหรับคำถามที่ดีจริงๆ:

ทางออกที่ดีที่สุดที่ฉันพบคือไม่น่าแปลกใจ tmux

คุณสามารถทำ Ctrl-B: setw ทำข้อมูลให้ตรงกันในบานหน้าต่าง tmux เพื่อเรซูเ คุณต้องเปิดการเชื่อมต่อ ssh ทั้งหมดของคุณในบานหน้าต่างที่แตกต่างกัน 1 หน้าต่างของ Tmux


0

อาจเป็นไปได้ที่จะใช้คำสั่งในหลาย ๆ โฮสต์? สมมติว่าโฮสต์ทั้งหมดได้รับการตั้งค่าใน. ssh / config

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


0

สร้างไฟล์ / etc / sxx / hosts

เติมเช่น:

[grp_ips]
1.1.1.1
2.2.2.2
3.3.3.3

แชร์คีย์ ssh บนทุกเครื่อง

ติดตั้ง sxx จากแพ็คเกจ:

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

จากนั้นเรียกใช้คำสั่งเช่นนั้น:

sxx username@grp_ips "whatever bash command"

เอาท์พุทอยู่ที่ไหน สถานะทางออกที่ไม่เป็นศูนย์มีการจัดการอย่างไร กรุณาอย่าตอบในความคิดเห็น; แก้ไขคำตอบของคุณเพื่อให้ชัดเจนและสมบูรณ์ยิ่งขึ้น
G-Man กล่าวว่า 'Reinstate Monica'

0

ใช้ Paramiko http://www.paramiko.org/และการทำงานแบบขนานตามเธรดhttps://docs.python.org/3/library/threading.html. ด้านล่างโค้ดช่วยให้สามารถรันคำสั่งหลายคำสั่งในแต่ละเซิร์ฟเวอร์พร้อมกัน!

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

หมายเหตุ: ทำซ้ำคำแนะนำข้างต้นสำหรับแต่ละเซิร์ฟเวอร์


0

ฉันคิดว่า "คาดหวัง" เป็นสิ่งที่คุณต้องการ
หลายคนไม่รู้ด้วยซ้ำว่ามีอยู่จริง มันเป็นโปรแกรมพื้นฐานที่จะสร้างคำถามและคำตอบที่เป็นไปได้ในนามของคุณ ไปที่ https://wiki.tcl-lang.org/page/Expect

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.