Tự động chạy các lệnh qua SSH trên nhiều máy chủ


46

Có một danh sách các địa chỉ IP trong tệp .txt, ví dụ:

1.1.1.1
2.2.2.2
3.3.3.3

Đằng sau mỗi địa chỉ IP đều có một máy chủ và trên mỗi máy chủ đều có một sshd chạy trên cổng 22. Không phải mọi máy chủ đều nằm trong known_hostsdanh sách (trên PC của tôi, Ubuntu 10.04 LTS / bash).

Làm cách nào tôi có thể chạy các lệnh trên các máy chủ này và thu thập đầu ra?

Lý tưởng nhất là tôi muốn chạy các lệnh song song trên tất cả các máy chủ.

Tôi sẽ sử dụng xác thực khóa công khai trên tất cả các máy chủ.

Dưới đây là một số cạm bẫy tiềm năng:

  • Ssh nhắc tôi đặt khóa ssh của máy chủ đã cho vào known_hoststệp của mình .
  • Các lệnh đã cho có thể trả về mã thoát khác, cho biết đầu ra có khả năng không hợp lệ. Tôi cần nhận ra điều đó.
  • Một kết nối có thể không được thiết lập cho một máy chủ nhất định, ví dụ do lỗi mạng.
  • Cần có thời gian chờ, trong trường hợp lệnh chạy lâu hơn dự kiến ​​hoặc máy chủ bị hỏng trong khi chạy lệnh.

Các máy chủ là AIX / ksh (nhưng tôi nghĩ điều đó không thực sự quan trọng.



1
Tôi nghĩ đó không phải là một bản sao, bởi vì liên kết bạn đề cập thậm chí không chứa SSH.
LanceBaynes

4
Nếu bạn chưa làm như vậy, bạn nên thiết lập máy chủ ssh trên tất cả các máy, tạo một cặp khóa riêng / chung trên máy bạn làm việc và sao chép khóa chung vào tài khoản trên máy chủ để tránh những rắc rối về mật khẩu. Điều đó áp dụng cho câu trả lời của tôi và cho cả @ demure.
Anthon

Câu trả lời:


14

Giả sử rằng bạn không thể cài đặt pssh hoặc người khác, bạn có thể làm điều gì đó tương tự:

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
Chính xác thì chờ gì trong kịch bản này ?? ty!
LanceBaynes

Điều gì xảy ra nếu khóa máy chủ không có trong tệp know_hosts của tôi?
LanceBaynes

5
đặt các kịch bản vào nền tạo ra các tiến trình con. Khi một tiến trình con thoát ra, tiến trình 'vị trí' và tài nguyên sẽ ở trong hệ thống cho đến khi tiến trình cha mẹ thoát ra hoặc tiến trình cha mẹ 'chờ đợi' cho con. Những quy trình 'chấm dứt bởi hiện tại' được gọi là các quy trình 'zombie'. Đó là hành vi tốt để dọn dẹp sau khi trẻ em cung cấp và đòi lại tài nguyên.
Arcege

1
Nếu không biết, thì điều đó có thể làm hỏng nó, nhưng bạn có thể thêm -o StrictHostKeyChecking=nođể tránh điều này. Tuy nhiên, tốt hơn hết là quét tất cả các máy chủ từ một dòng lệnh trước để có thể thêm các khóa máy chủ.
Arcege

1
Như tôi đã đề cập, sau khi chương trình ssh được đặt vào nền và sau khi thoát, tài nguyên vẫn được giữ. Các waitlệnh đòi những nguồn lực, bao gồm cả mã quá trình trở lại (cách processs thoát). Sau đó, nếu sau này trong chương trình, bạn đặt một quy trình khác, giả sử nén, ở chế độ nền và cần chờ, sau đó không có vòng lặp này, chờ đợi sẽ lấy lại một trong các chương trình ssh đã hoàn thành, không phải nén - vẫn có thể nén đang chạy Bạn sẽ nhận được một trạng thái trở lại trên quá trình con sai. Nó là tốt để làm sạch sau khi chính mình.
Arcege

61

Có một số công cụ hiện có cho phép bạn đăng nhập và thực hiện hàng loạt lệnh trên nhiều máy cùng một lúc. Đây là một cặp vợ chồng:


1
Bạn có thể muốn thêm pdsh vào danh sách.
Riccardo Murri

1
Tôi thấy cụm sao khá trực quan để sử dụng. Chỉ 2 xu của tôi ...
josinalvo

1
Tôi sử dụng pssh thường xuyên. Nó hoạt động rất tốt, mặc dù tôi ước tôi có thể nói với nó rằng một số lệnh từ xa nhất định sẽ có mã thoát khác không và điều đó không có nghĩa là có lỗi. Đó hoàn toàn là mỹ phẩm.
Anthony Clark

1
@AnthonyClark bạn có thể thêm một cái gì đó như "|| true" vào các lệnh đó.
exic

16

Nếu bạn thích Python scripting hơn bashscripting, thì Fabric có thể là công cụ dành cho bạn.

Từ trang chủ Vải :

Fabric là một thư viện và công cụ dòng lệnh Python (2.5 trở lên) để hợp lý hóa việc sử dụng SSH để triển khai ứng dụng hoặc quản trị hệ thống.

Nó cung cấp một bộ thao tác cơ bản để thực thi các lệnh shell cục bộ hoặc từ xa (thông thường hoặc thông qua sudo) và tải lên / tải xuống các tệp, cũng như chức năng phụ trợ như nhắc người dùng đang chạy để nhập hoặc hủy bỏ thực thi.

Việc sử dụng điển hình liên quan đến việc tạo một mô-đun Python chứa một hoặc nhiều hàm, sau đó thực hiện chúng thông qua công cụ dòng lệnh fab.


Vải v1 thật tuyệt vời. Thật không may, Fabric v2 đã loại bỏ hầu hết các tính năng giúp nó hữu ích cho trường hợp sử dụng này - hiện không khuyến nghị (tháng 6 năm 2018).
Meekohi

11

Tôi sử dụng GNU song song cho điều đó, cụ thể nhất là bạn có thể sử dụng công thức này :

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

Với your.txtviệc là tập tin với địa chỉ IP / tên máy chủ.


không có cách nào khác chỉ sử dụng ssh Vì tôi đang sử dụng máy chủ của công ty, tôi không muốn cài đặt các gói bổ sung
Özzesh

Chắc chắn, tôi đã từng làm điều này trước khi sshtồn tại, nhưng bạn cần một số cách để đăng nhập vào các máy tính khác và những cách đó được sử dụng để bảo mật ít hơn (như rsh). Bạn không mô tả những gì bạn đang sử dụng bây giờ để chuyển từ máy này sang máy khác ( telnet?, rsh?).
Anthon

1
@ Zzesh có chỉ trên bộ điều khiển
Anthon

1
@ Zzesh Xem lý do của bạn không cài đặt GNU Parallel có được nêu trên oletange.blogspot.dk/2013/04/why-not-install-gnu-abul.html
Ole Tange

1
@OleTange Chỉ cần nhận ra ai đã nhận xét về câu trả lời của tôi% -). Cảm ơn cho phần mềm tuyệt vời này.
Anthon

8

Thiết lập rất cơ bản:

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

Xác thực với tên / mật khẩu thực sự không có ý tưởng tốt. Bạn nên thiết lập một khóa riêng cho việc này:

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

1
đây là người tôi đã tìm kiếm !!!!! Cảm ơn michas
Özzesh

đoạn script trên hoạt động tốt với tôi nhưng sau khi thực thi trong 10 máy chủ thì đoạn script không phản hồi. Làm cách nào tôi có thể đăng xuất khỏi máy chủ ssh mà tôi đang kết nối?
Özz

Bạn không cần phải đăng xuất một cách rõ ràng. "Kịch bản" này sẽ chỉ chạy ssh $host $commandcho mỗi máy chủ. Cố gắng chạy các lệnh đó bằng tay để tìm hiểu những gì đang xảy ra.
michas

4

Tôi đề nghị Ansible.cc . Đó là một trình quản lý cấu hình và bộ điều phối lệnh.


2

Tôi nghĩ rằng bạn đang tìm kiếm pssh và các phiên bản song song có liên quan của scp, rsync, v.v.


Đây là một phiếu bầu để bị xóa, nhưng câu trả lời sau này là +10. Làm cho cảm giác hoàn hảo
Michael Mrozek

@MichaelMrozek Tệ hơn bạn biết. Thứ hai trong số hai VTD là của tôi trong một tai nạn nhấp chuột hạnh phúc. Tôi đã mở tab này trong một vài ngày với ý định gắn cờ hoặc ping bạn để hoàn nguyên VTD của tôi nếu nó bị xóa. Có lẽ bạn chỉ cần lật nó bây giờ để xóa phiếu.
Caleb

@Caleb Đã sửa nó
Michael Mrozek

2

Tôi đã xây dựng một công cụ nguồn mở có tên là Overcast để làm cho việc này trở nên dễ dàng hơn.

Đầu tiên bạn xác định máy chủ của mình:

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

Sau đó, bạn có thể chạy nhiều lệnh và tệp tập lệnh trên chúng, theo tuần tự hoặc song song, như vậy:

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

2

Các Hypertable dự án gần đây đã bổ sung thêm một công cụ ssh đa-host. Công cụ này được xây dựng với libssh và thiết lập các kết nối và đưa ra các lệnh không đồng bộsong song để tối đa hóa song song. Xem Công cụ SSH nhiều máy chủ để biết tài liệu đầy đủ. Để chạy lệnh trên một tập hợp các máy chủ, bạn sẽ chạy nó như sau:

$ ht ssh 1.1.1.1,2.2.2.2,3.3.3.3 uptime

Bạn cũng có thể chỉ định tên máy chủ hoặc mẫu IP, ví dụ:

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

Nó cũng hỗ trợ một --random-start-delay <millis>tùy chọn sẽ trì hoãn việc bắt đầu lệnh trên mỗi máy chủ theo khoảng thời gian ngẫu nhiên trong khoảng từ 0 đến <millis>mili giây. Tùy chọn này có thể được sử dụng để tránh các vấn đề bầy đàn khi lệnh đang chạy truy cập vào một tài nguyên trung tâm.


2

Tôi đã phát triển collnode Rất đơn giản và hiệu quả để thực hiện các tác vụ trong một số máy chủ (bao gồm cả cửa sổ)

Cách sử dụng Sưu tầm:

  1. Tạo danh sách máy chủ, để làm việc với:

    # cat hosts.file
    server1
    server2
    server3
    server4
    server5
    
  2. Thực thi CollectionNode vượt qua danh sách phục vụ:

    collectnode --file servers.txt --command='cat /etc/httpd/conf/httpd.conf |grep ^User'
    
  3. Về mặt quang học, có thể lọc kết quả, ví dụ lệnh này chỉ hiển thị máy chủ nơi điều kiện được thực hiện.

    collectnode --file servers.txt --command='cat /etc/httpd/conf/httpd.conf |grep ^User' --where="command contain User"
    

https://collectnode.com/5-t task-collectnode-can-help-managing-servers/


1
Có vẻ như bạn là nhà phát triển của Sưu tầm. Trong trường hợp đó, bạn nên tiết lộ rằng trong câu trả lời hoặc đây chỉ là thư rác.
muru

xin lỗi, đó không phải là ý định của tôi, câu trả lời được sửa đổi để cụ thể hơn.
fvidalmolina

1

Chỉ cần một headup cho một câu hỏi thực sự tốt đẹp:

Giải pháp tốt nhất tôi tìm thấy là, không quá ngạc nhiên, tmux.

Bạn có thể thực hiện Ctrl-B: setw sync-panes trong tmux để phục hồi tuyệt vời. Bạn phải mở tất cả các kết nối ssh của mình, trong các ô khác nhau của 1 cửa sổ Tmux cho việc này.


0

Có lẽ một cái gì đó như thế này hoạt động, để chạy lệnh trên nhiều máy chủ? giả sử tất cả các máy chủ được thiết lập trong .ssh / config để đăng nhập không cần mật khẩu.

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


0

Tạo một tập tin / etc / sxx / hosts

cư trú như vậy:

[grp_ips]
1.1.1.1
2.2.2.2
3.3.3.3

chia sẻ khóa ssh trên tất cả các máy.

Cài đặt sxx từ gói:

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

Sau đó chạy lệnh như vậy:

sxx username@grp_ips "whatever bash command"

Đầu ra được viết ở đâu? Các trạng thái thoát khác không được xử lý như thế nào? Xin vui lòng không trả lời trong các ý kiến; chỉnh sửa câu trả lời của bạn để làm cho nó rõ ràng và đầy đủ hơn.
G-Man nói 'Phục hồi Monica'

0

Sử dụng Paramiko http://www.paramiko.org/ và song song dựa trên chủ đề https://docs.python.org/3/l Library / threading.html .Bây mã cho phép thực thi song song nhiều lệnh trên mỗi máy chủ!

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

Lưu ý: lặp lại hướng dẫn trên cho mỗi máy chủ.


0

Tôi nghĩ rằng "mong đợi" là những gì bạn cần.
Nhiều người thậm chí không biết nó tồn tại. Đây là một chương trình dựa trên tcl sẽ thay mặt bạn đặt câu hỏi và câu trả lời có thể. Hãy xem https://wiki.tcl-lang.org/page/Expect

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.