Làm cách nào để chạy tập lệnh bash cục bộ trên các máy từ xa thông qua ssh?


51

Tôi đang tìm cách đẩy cấu hình từ một máy trung tâm sang một số máy từ xa mà không cần phải cài đặt bất cứ thứ gì trên các máy từ xa.

Mục đích là để làm một cái gì đó giống như bạn sẽ tìm thấy với các công cụ như cfengine, nhưng trên một bộ máy không có đại lý được thiết lập. Đây thực sự có thể là một kỹ thuật tốt để thiết lập cfagenttrên một tập hợp các máy từ xa hiện có.



1
Các câu hỏi thực tế có 23 câu hỏi trong đó bản sao trên SO có 55: P
MoJo

Câu trả lời:


55

Bạn có thể truyền một tập lệnh và để nó thực thi một cách nhanh chóng bằng cách đưa nó vào và thực thi một trình bao.

ví dụ

echo "ls -l; echo 'Hello World'" | ssh me@myserver /bin/bash

Đương nhiên, "ls -l; echo 'Hello World'"phần này có thể được thay thế bằng tập lệnh bash được lưu trữ trong một tệp trên máy cục bộ.

ví dụ

cat script.sh | ssh me@myserver /bin/bash

Chúc mừng!


2
Làm thế nào để làm cho hoạt động này như sudo trên system.eg từ xa Nếu tôi đã đăng nhập vào máy chủ từ xa tôi thường sẽ chạy như sudo -u testuser script.sh
Sharjeel

Điều gì xảy ra nếu tập lệnh tôi đang gọi liên quan đến tương tác của người dùng ???
Abhimanyu Srivastava 18/03/13

20

Có một số cách để làm điều đó.

1:

ssh user@remote_server 'bash -s' < localfile

2:

cat localfile  | ssh user@remote_server

3:

ssh user@remote_server "$(< localfile)"

số 3 là cách ưa thích của tôi, nó cho phép các lệnh tương tác, vd su -S service nginx restart

(# 1 sẽ sử dụng phần còn lại của tập lệnh làm đầu vào cho câu hỏi mật khẩu khi bạn sử dụng su -S.)


4
Về việc chạy tập lệnh cục bộ trên máy từ xa - Có cách nào để gửi biến làm đối số cho máy từ xa không ..? tức là cùng với tập lệnh, tôi muốn gửi một biến (có nhiều dòng) làm đối số cho máy từ xa. Kịch bản sau đó dự định sử dụng biến.

13

Tôi muốn giới thiệu Vải python cho mục đích này:

#!/usr/bin/python
# ~/fabfile.py

from fabric_api import *

env.hosts = ['host1', 'host2']
def deploy_script():
    put('your_script.sh', 'your_script.sh', mode=0755)
    sudo('./your_script.sh')

# from shell
$ fab deploy_script

Bạn sẽ có thể sử dụng ở trên để bắt đầu. Tham khảo tài liệu tuyệt vời của Fabric để làm phần còn lại. Là một phụ lục, bạn hoàn toàn có thể viết tập lệnh của mình trong Fabric - không cần sao chép, tuy nhiên cần lưu ý rằng để thay đổi tập lệnh trên tất cả các máy, bạn chỉ cần chỉnh sửa bản sao và triển khai lại. Hơn nữa, với việc sử dụng API nhiều hơn một chút, bạn có thể sửa đổi tập lệnh dựa trên máy chủ nào hiện đang chạy và / hoặc các biến khác. Đó là một loại kỳ vọng pythonic.


Tôi không nghĩ rằng điều này trả lời chính xác câu hỏi, nhưng tôi thích ý tưởng đó và tôi có thể xem Fabric là một công cụ hữu ích.
tremoloqui

1
@tremoloqui Fabric là một trình bao bọc python xung quanh ssh - không cần cài đặt gì trên các máy đích, lưu tập lệnh đang được đẩy. Mà, nếu được viết lại dưới dạng một loạt các lệnh Fabric (sử dụng runsudo), thậm chí không cần thiết.
Izkata

5

Đây chính xác là những gì Ansible được sử dụng cho. Không có tác nhân, bạn chỉ cần tạo một tệp văn bản có tên:

/etc/ansible/hosts

với nội dung trông giống như:

[webhosts]
web[1-8]

Điều này sẽ chỉ định rằng các máy "web1, web2 ... web8" nằm trong nhóm "webhosts". Sau đó, bạn có thể làm những việc như:

ansible webhosts -m service -a "name=apache2 state=restarted" --sudo

để khởi động lại dịch vụ apache2 trên tất cả các máy của bạn, sử dụng sudo.

Bạn có thể thực hiện các lệnh bay như:

ansible webhosts -m shell -a "df -h"

hoặc bạn có thể chạy một tập lệnh cục bộ trên máy từ xa:

ansible webhosts -m script -a "./script.sh"

hoặc bạn có thể tạo một playbook (tra cứu tài liệu để biết chi tiết) với một cấu hình hoàn chỉnh mà bạn muốn các máy chủ của mình tuân thủ và triển khai nó với:

ansible-playbook webplaybook.yml

Về cơ bản, bạn có thể bắt đầu sử dụng nó như một công cụ dòng lệnh để chạy các lệnh trên nhiều máy chủ và mở rộng việc sử dụng nó thành một công cụ cấu hình hoàn chỉnh khi bạn thấy phù hợp.


3
Tôi thích ansible nhiều như anh chàng tiếp theo, nhưng nếu anh ta hỏi về kịch bản, thì ansible có một mô-đun kịch bản thực sự hay :ansible webhosts -m script script.sh
ptman

1
Tất cả các câu trả lời khác liên quan đến một kịch bản bash, nhưng đó không phải là những gì anh ấy yêu cầu cụ thể. Ông chỉ nói đẩy cấu hình vào máy từ xa. Nhưng đề cập tốt đến mô-đun kịch bản :)
seumasmac

Hãy bỏ phiếu cho câu trả lời này! Đây là cách để làm điều đó!
gà con

@ptman Tôi chỉ nhận thấy rằng trong khi anh ấy không đề cập đến một kịch bản trong câu hỏi, anh ấy làm trong tiêu đề! Lấy làm tiếc. Tôi đã cập nhật.
seumasmac

3

Như đã giải thích trong câu trả lời này, bạn có thể sử dụng heredoc :

ssh user@host <<'ENDSSH'
#commands to run on remote host
ENDSSH

Bạn phải cẩn thận với heredoc, vì nó chỉ gửi văn bản, nhưng nó không thực sự chờ phản hồi. Điều đó có nghĩa là nó sẽ không chờ lệnh của bạn được thực thi.


1

Câu trả lời ở đây ( https://stackoverflow.com/a/2732991/4752883 ) hoạt động rất tốt nếu bạn đang cố chạy tập lệnh trên máy linux từ xa bằng cách sử dụng plinkhoặc ssh. Nó sẽ hoạt động nếu tập lệnh có nhiều dòng trên linux.

** Tuy nhiên, nếu bạn đang cố chạy một tập lệnh bó nằm trên một linux/windowsmáy cục bộ và máy từ xa của bạn Windows, và nó bao gồm nhiều dòng sử dụng **

plink root@MachineB -m local_script.bat

nó sẽ không làm việc

Chỉ dòng đầu tiên của tập lệnh sẽ được thực thi. Đây có lẽ là một hạn chế plink.

Giải pháp 1:

Để chạy tập lệnh bó đa dòng (đặc biệt nếu nó tương đối đơn giản, bao gồm một vài dòng):

Nếu tập lệnh bó ban đầu của bạn như sau

cd C:\Users\ipython_user\Desktop 
python filename.py

bạn có thể kết hợp các dòng lại với nhau bằng cách sử dụng dấu phân cách "&&" như sau trong local_script.battệp của mình như sau https://stackoverflow.com/a/8055390/4752883 :

cd C:\Users\ipython_user\Desktop && python filename.py

Sau khi thay đổi này, bạn có thể chạy tập lệnh như được chỉ ra ở đây bởi @ JasonR.Coombs: https://stackoverflow.com/a/2732991/4752883

Giải pháp 2:

Nếu tập lệnh bó của bạn tương đối phức tạp, có thể tốt hơn là sử dụng tập lệnh bó, đóng gói lệnh plink cũng như được chỉ ra ở đây bởi @Martin https://stackoverflow.com/a/32196999/4752883 :

rem Open tunnel in the background
start plink.exe -ssh [username]@[hostname] -L 3307:127.0.0.1:3306 -i "[SSH
key]" -N

rem Wait a second to let Plink establish the tunnel 
timeout /t 1

rem Run the task using the tunnel
"C:\Program Files\R\R-3.2.1\bin\x64\R.exe" CMD BATCH qidash.R

rem Kill the tunnel
taskkill /im plink.exe

0

Tại sao không chỉ đơn giản là sao chép tập lệnh trước, sau đó chạy nó?

scp your_script.sh the_server:
ssh the_server "chmod +x your_script.sh; ./your_script.sh"

Tất nhiên bạn nên cẩn thận không tải nó lên một nơi có thể ghi được trên thế giới, vì vậy không ai khác có thể mân mê nó trước khi bạn chạy nó (có thể là root).


1
Lý do tôi không muốn tải lên tập lệnh là vì vậy nó không phải được quản lý và có những rủi ro mà bạn đề cập. Ngoài ra, đối với tôi, nó đơn giản hơn quá trình tải lên, xử lý và xóa (tùy chọn) nhiều bước.
tremoloqui

0

Viết lại tập lệnh theo cách mà mỗi lệnh trong đó đã được thêm tiền tố vào ssh và tên máy chủ / ip hoặc danh sách được truyền cho tập lệnh dưới dạng đối số (giả sử bạn đã thiết lập xác thực khóa mật khẩu / ssh-agent). Một số công việc có thể cần thiết để chuyển chính xác lỗi / trả lại mã từ các lệnh từ xa ....


0

Nếu tập lệnh không quá lớn và bạn đang sử dụng bash hoặc ksh ...

ssh vm24 -t bash -c "$(printf "%q" "$(< shell-test.sh )")"

Cả stdin và stdout đều hoạt động chính xác nhưng tập lệnh bị giới hạn ở kích thước đối số (thường là khoảng 100k). Các đối số cho tập lệnh có thể hoạt động, ở cuối dòng, có thể theo sau một đối số "-" bổ sung. "-T" để phân bổ một pty là tùy chọn.

Cẩn thận: Điều này gây nhầm lẫn khi hoàn thành bash, đừng nhấn tab.

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.