Thực hiện các lệnh từ xa, tách hoàn toàn khỏi kết nối ssh


48

Tôi có 2 máy tính, localpcremoteserver.

Tôi cần localpcphải thực thi một số lệnh trên remoteserver. Một trong những điều nó cần làm là bắt đầu một kịch bản sao lưu chạy trong một số giờ. Tôi muốn lệnh trên localpclửa cháy và sau đó được vận hành hoàn toàn độc lập remoteserver, giống như localpcchưa từng có ở nơi đầu tiên.

Đây là những gì tôi đã làm cho đến nay:

remoteserver chứa có kịch bản:

/root/backup.sh

localpc được lên kế hoạch để chạy này:

ssh root@remoteserver 'nohup /root/backup.sh' &

Tôi đang làm điều này đúng cách? Có cách nào tốt hơn để làm điều này? Tôi sẽ gặp rắc rối khi làm theo cách này?


stackoverflow.com/questions/19996089/...stackoverflow.com/questions/29142/... cung cấp một số phương pháp hữu ích cho vấn đề này không sử dụng màn hình / tmux vv ...
Paul

Câu trả lời:


47

Bạn có thể nên sử dụng screentrên máy chủ từ xa, để có một lệnh tách rời thực sự:

ssh root@remoteserver screen -d -m ./script

Tôi thích ý tưởng này. Khi kịch bản kết thúc, màn hình vẫn sẽ chạy qua ... và tôi phải kết nối lại với nó vào lần tới khi tôi muốn chạy nó, phải không?
LVLAaron

@AaronJAnderson: không, cho rằng lệnh không phải là trình bao, khi nó kết thúc thì phiên màn hình cũng chấm dứt.
enzotib

52

Đóng, nhưng không chính xác.

Độc lập với bất kỳ thiết bị đầu cuối

ssh root@remoteserver '/root/backup.sh </dev/null >/var/log/root-backup.log 2>&1 &'

Bạn cần đóng tất cả các mô tả tệp được kết nối với ổ cắm ssh, vì phiên ssh sẽ không đóng miễn là một số quy trình từ xa có ổ cắm mở. Nếu bạn không quan tâm đến đầu ra của tập lệnh (có lẽ vì tập lệnh tự xử lý việc ghi vào tệp nhật ký), hãy chuyển hướng nó đến /dev/null(nhưng lưu ý rằng điều này sẽ ẩn các lỗi như không thể khởi động tập lệnh).

Sử dụng nohupkhông có tác dụng hữu ích ở đây. nohupsắp xếp cho chương trình nó chạy không nhận tín hiệu HUP nếu thiết bị đầu cuối điều khiển của chương trình biến mất, nhưng ở đây không có thiết bị đầu cuối ở nơi đầu tiên, vì vậy sẽ không có gì để gửi SIGHUP đến quá trình ngoài màu xanh. Ngoài ra, nohupchuyển hướng đầu ra tiêu chuẩn và lỗi tiêu chuẩn (nhưng không phải đầu vào tiêu chuẩn) vào một tệp, nhưng chỉ khi chúng được kết nối với một thiết bị đầu cuối, một lần nữa, chúng không xảy ra.

Tháo ra từ một thiết bị đầu cuối

 aaron@localpc$ ssh root@remoteserver
 root@remoteserver# nohup /root/backup.sh </dev/null &
 nohup: appending output to `nohup.out'
 [1] 12345
 root@remoteserver# exit
 aaron@localpc$ 

Sử dụng nohupđể tách tập lệnh khỏi thiết bị đầu cuối kiểm soát của nó để nó không nhận được SIGHUP khi thiết bị đầu cuối biến mất. nohupcũng chuyển hướng đầu ra tiêu chuẩn và lỗi tiêu chuẩn của tập lệnh sang một tệp được gọi nohup.outnếu chúng được kết nối với thiết bị đầu cuối; bạn phải tự chăm sóc đầu vào tiêu chuẩn.

Giữ một thiết bị đầu cuối từ xa

Nếu bạn muốn giữ lệnh chạy trong một thiết bị đầu cuối từ xa nhưng không được gắn vào phiên SSH, hãy chạy nó trong bộ ghép kênh đầu cuối như Screen hoặc Tmux .

ssh root@remoteserver 'screen -S backup -d -m /root/backup.sh'

Sau này bạn có thể kết nối lại với thiết bị đầu cuối nơi tập lệnh đang chạy bằng cách gọi screen -S backup -rdlà root trên máy đó.

Tự động hóa một lệnh từ xa

Để bảo mật tốt hơn một chút, đừng mở đăng nhập gốc từ xa trực tiếp quá rộng rãi. Tạo một cặp khóa có mục đích đặc biệt và cung cấp cho nó một lệnh bắt buộc /root/.ssh/authorized_keys. Nội dung của tệp khóa công khai là AAAA…== wibble@example.com; thêm một danh sách các tùy chọn được phân tách bằng dấu phẩy, bao gồm command="…"chỉ định rằng khóa chỉ có thể được sử dụng để thực thi lệnh cụ thể này. Hãy chắc chắn giữ tất cả các tùy chọn và chìa khóa trên một dòng.

command="/root/backup.sh </dev/null >/dev/null 2>/dev/null &",no-port-forwarding,no-agent-forwarding,no-x11-forwarding,no-pty,no-user-rc AAAA…== wibble@example.com

Tôi đã thử lệnh đầu tiên bạn liệt kê. Nó không nền trên hộp thực thi lệnh. Con trỏ chỉ ngồi đó và chờ hoàn thành ... có lẽ đó là một lỗi?
LVLAaron

Bạn có thể cần chuyển hướng stdin sang / dev / null trên hệ thống từ xa. Đó có thể là lý do tại sao ssh không thoát.
KeithB

Tôi sẽ thêm -ftùy chọn để đưa ssh vào 'nền' (nghĩa là chấm dứt, đóng kết nối) ở phía địa phương. Điều này sẽ làm việc kết hợp với &. nohuplà tùy chọn trong trường hợp này, nhưng bạn có thể cân nhắc sử dụng setsidthay thế.
Alexios

@KeithB Chuyển hướng stdin là một phần của nó, nhưng tôi cũng cần chuyển hướng stdout và stderr: nohup sẽ không làm điều đó ở đây vì chúng không phải là thiết bị đầu cuối, và trên thực tế nohup không hữu ích ở đây.
Gilles 'SO- ngừng trở nên xấu xa'

1
@erikbwork Xin lưu ý rằng tôi hoàn toàn không có manh mối nào về những điều đó, nhưng sau khi thảo luận và nhận xét: Gilles không sử dụng tùy chọn -t trong các lệnh của mình, vì vậy không có thiết bị đầu cuối giả nào được thiết lập, cả máy khách cũng như máy chủ bên. Do đó, không có HUP sẽ được gửi.
Binarus

12

Công thức tiêu chuẩn để chạy lệnh từ xa từ đăng nhập từ xa như SSH là như sau:

nohup command </dev/null >command.log 2>&1 &

Nếu commandlà một tập lệnh shell chăm sóc việc đăng nhập vào một tệp, thì bạn có thể thay đổi command.logthành /dev/null. Một khi bạn bắt đầu điều này, đăng xuất ngay lập tức.

Bạn cần mọi thứ trên dòng đó.

nohup báo cho shell không làm phiền quá trình nếu phiên đăng nhập bị ngắt kết nối.

</dev/null nói với nó không bao giờ chờ đợi đầu vào

>command.log bảo nó gửi bất kỳ tin nhắn nào đến tệp nhật ký có tên này

2>&1bảo nó gửi bất kỳ thông điệp stderr nào đến cùng một tệp nhật ký. Trong một số trường hợp, tốt hơn là có hai tệp, tệp thứ hai để thu thập thông báo lỗi và tệp thứ nhất để thu thập thông báo hoạt động bình thường. Điều đó có thể giúp dễ dàng xác minh rằng mọi thứ hoạt động chính xác.

& nói với nó để tách quá trình này và chạy nó trong nền như một quá trình daemon.


10

Chủ đề này rất hữu ích nhưng giải pháp của tôi phải khác một chút.

Tôi không thích giải pháp màn hình vì nó để lại một quá trình màn hình đang chạy mà tôi không cần. Các chuyển hướng và nohups được sử dụng như thế này:

ssh root@remoteserver '/root/backup.sh </dev/null >/var/log/root-backup.log 2>&1 &'

KHÔNG làm việc cho tôi khi được sử dụng với lệnh ssh.

Tôi đã tạo một tập lệnh bao bọc trên máy từ xa chạy tập lệnh thực tế. Kịch bản lệnh bao bọc đặt chuyển hướng và nohup. Một cái gì đó như thế này:

backupwrapper.sh:
nohup backup.sh > /dev/null 2>&1 &

Sau đó, trên máy khách của tôi, tôi chạy (thông báo không chuyển hướng):

# ssh remotemachine "backupwrapper.sh"
#

Lệnh ssh ngay lập tức trả về, kết nối bị ngắt và tập lệnh được chạy.


6

Như Nils nói , đó là rủi ro bảo mật khi cho phép root đăng nhập thông qua ssh. Và tôi khuyên không nên chạy bất kỳ công việc đáng kể nào trên máy mà không có nhật ký. Nếu có gì sai, bạn sẽ muốn có một số thông báo khắc phục sự cố. Có những câu trả lời khác chỉ cho bạn cách làm điều đó. Nhưng đây là cách tôi khuyên bạn nên hoàn thành những gì bạn yêu cầu. Tất cả được tích hợp vào sh (1). Không cần màn hình GNU (mặc dù tôi nghĩ đó là một giải pháp thông minh). Nối chuỗi này vào lệnh của bạn : >&- 2>&- <&- &. >&-có nghĩa là stdout gần. 2>&-có nghĩa là stderr gần. <&-có nghĩa là gần stdin. &có nghĩa là chạy trong nền, ví dụ

$ ssh myhost 'sleep 30 >&- 2>&- <&- &'
# ssh returns right away, and your sleep job is running remotely
$

0

Bạn nên nền lệnh từ xa trên remoteserver. Cách bạn làm sẽ làm nền cho lệnh ssh localpc.

Ngoài ra, đó là một ý tưởng tồi để cho phép root-ssh.

Vì vậy, thiết lập trên remoteserver: Một dòng sudoers sẽ chạy /root/backup.shnhư root bởi người dùng backup.

Bạn có thể tạo người dùng đó mà không cần mật khẩu "tốt".

Đặt lệnh sudo /root/backup.sh &dưới dạng lệnh vào ~backup/.ssh/authorized_keys- cùng với khóa chung từ localpc(bất kỳ ai kích hoạt tập lệnh đó).


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.